diff --git a/docs/docs/how-to/logging/src/log-context/handler.go b/docs/docs/how-to/logging/src/log-context/handler.go index 570295d76..0e231bbcc 100644 --- a/docs/docs/how-to/logging/src/log-context/handler.go +++ b/docs/docs/how-to/logging/src/log-context/handler.go @@ -7,7 +7,6 @@ import ( "github.com/justtrackio/gosoline/pkg/cfg" db_repo "github.com/justtrackio/gosoline/pkg/db-repo" - "github.com/justtrackio/gosoline/pkg/httpserver/crud" "github.com/justtrackio/gosoline/pkg/log" "github.com/justtrackio/gosoline/pkg/mdl" ) @@ -41,7 +40,7 @@ type UpdateInput struct { type TodoCrudHandlerV0 struct { // highlight-next-line logger log.Logger - repo db_repo.Repository + repo db_repo.Repository[uint, *Todo] } // snippet-end: crud handler v0 @@ -49,9 +48,9 @@ type TodoCrudHandlerV0 struct { // snippet-start: new todo crud handler func NewTodoCrudHandler(ctx context.Context, config cfg.Config, logger log.Logger) (*TodoCrudHandlerV0, error) { var err error - var repo db_repo.Repository + var repo db_repo.Repository[uint, *Todo] - if repo, err = db_repo.New(config, logger, settings); err != nil { + if repo, err = db_repo.New[uint, *Todo](config, logger, settings); err != nil { return nil, fmt.Errorf("can not create db_repo.Repositorys: %w", err) } @@ -66,18 +65,10 @@ func NewTodoCrudHandler(ctx context.Context, config cfg.Config, logger log.Logge // snippet-end: new todo crud handler -func (h TodoCrudHandlerV0) GetRepository() crud.Repository { +func (h TodoCrudHandlerV0) GetRepository() db_repo.Repository[uint, *Todo] { return h.repo } -func (h TodoCrudHandlerV0) GetModel() db_repo.ModelBased { - return &Todo{} -} - -func (h TodoCrudHandlerV0) GetCreateInput() interface{} { - return &CreateInput{} -} - // snippet-start: truncate func truncate(ctx context.Context, text string) string { r := []rune(text) @@ -97,57 +88,47 @@ func truncate(ctx context.Context, text string) string { // snippet-end: truncate // snippet-start: transform create -func (h TodoCrudHandlerV0) TransformCreate(ctx context.Context, input interface{}, model db_repo.ModelBased) error { - in := input.(*CreateInput) - m := model.(*Todo) - +func (h TodoCrudHandlerV0) TransformCreate(ctx context.Context, in *CreateInput) (*Todo, error) { // highlight-start localctx := log.InitContext(ctx) - m.Text = truncate(localctx, in.Text) - // highlight-end - m.DueDate = in.DueDate + m := &Todo{ + Text: truncate(localctx, in.Text), + // highlight-end + DueDate: in.DueDate, + } - return nil + return m, nil } // snippet-end: transform create -func (h TodoCrudHandlerV0) GetUpdateInput() interface{} { - return &UpdateInput{} -} - // snippet-start: transform update -func (h TodoCrudHandlerV0) TransformUpdate(ctx context.Context, input interface{}, model db_repo.ModelBased) error { - in := input.(*UpdateInput) - m := model.(*Todo) - +func (h TodoCrudHandlerV0) TransformUpdate(ctx context.Context, in *UpdateInput, m *Todo) (*Todo, error) { // highlight-start localctx := log.InitContext(ctx) m.Text = truncate(localctx, in.Text) // highlight-end - return nil + return m, nil } // snippet-end: transform update -func (h TodoCrudHandlerV0) TransformOutput(ctx context.Context, model db_repo.ModelBased, apiView string) (interface{}, error) { +func (h TodoCrudHandlerV0) TransformOutput(ctx context.Context, model *Todo, apiView string) (*Todo, error) { return model, nil } -func (h TodoCrudHandlerV0) List(ctx context.Context, qb *db_repo.QueryBuilder, apiView string) (interface{}, error) { +func (h TodoCrudHandlerV0) List(ctx context.Context, qb *db_repo.QueryBuilder, apiView string) ([]*Todo, error) { var err error - - // Instatiate a list of Todo objects, called result. - result := make([]*Todo, 0) + var result []*Todo // Query the database using a Context and a QueryBuilder. If it finds the results, it sets them on result. Otherwise, it returns an error. - if err = h.repo.Query(ctx, qb, &result); err != nil { + if result, err = h.repo.Query(ctx, qb); err != nil { return nil, fmt.Errorf("can not query todo items: %w", err) } // Transform each result with TransformOutput(). - out := make([]interface{}, len(result)) + out := make([]*Todo, len(result)) for i, res := range result { if out[i], err = h.TransformOutput(ctx, res, apiView); err != nil { return nil, err diff --git a/docs/docs/how-to/logging/src/log-context/main.go b/docs/docs/how-to/logging/src/log-context/main.go index d1a9ab6d9..ed8f2c823 100644 --- a/docs/docs/how-to/logging/src/log-context/main.go +++ b/docs/docs/how-to/logging/src/log-context/main.go @@ -21,7 +21,7 @@ func main() { def := &httpserver.Definitions{} var err error - var handler crud.Handler + var handler crud.Handler[CreateInput, UpdateInput, *Todo, uint, *Todo] // Created a new CRUD handler. if handler, err = NewTodoCrudHandler(ctx, config, logger); err != nil { diff --git a/docs/docs/quickstart/http-server/src/write-crud-sql-app/handler.go b/docs/docs/quickstart/http-server/src/write-crud-sql-app/handler.go index 09c68726d..10b83f116 100644 --- a/docs/docs/quickstart/http-server/src/write-crud-sql-app/handler.go +++ b/docs/docs/quickstart/http-server/src/write-crud-sql-app/handler.go @@ -8,7 +8,6 @@ import ( "github.com/justtrackio/gosoline/pkg/cfg" db_repo "github.com/justtrackio/gosoline/pkg/db-repo" - "github.com/justtrackio/gosoline/pkg/httpserver/crud" "github.com/justtrackio/gosoline/pkg/log" "github.com/justtrackio/gosoline/pkg/mdl" ) @@ -51,7 +50,7 @@ type UpdateInput struct { // snippet-start: crud handler type TodoCrudHandlerV0 struct { - repo db_repo.Repository + repo db_repo.Repository[uint, *Todo] } // snippet-end: crud handler @@ -60,10 +59,10 @@ type TodoCrudHandlerV0 struct { func NewTodoCrudHandler(ctx context.Context, config cfg.Config, logger log.Logger) (*TodoCrudHandlerV0, error) { // Declare `error` and `repo` variables. var err error - var repo db_repo.Repository + var repo db_repo.Repository[uint, *Todo] // Try to create a new `Repository` given a configuration, a logger, and settings. If there is an error, you return it. - if repo, err = db_repo.New(config, logger, settings); err != nil { + if repo, err = db_repo.New[uint, *Todo](config, logger, settings); err != nil { return nil, fmt.Errorf("can not create db_repo.Repositorys: %w", err) } @@ -79,79 +78,52 @@ func NewTodoCrudHandler(ctx context.Context, config cfg.Config, logger log.Logge // snippet-end: todo constructor // snippet-start: get repo -func (h TodoCrudHandlerV0) GetRepository() crud.Repository { +func (h TodoCrudHandlerV0) GetRepository() db_repo.Repository[uint, *Todo] { return h.repo } // snippet-end: get repo -// snippet-start: get model -func (h TodoCrudHandlerV0) GetModel() db_repo.ModelBased { - return &Todo{} -} - -// snippet-end: get model - -// snippet-start: create input -func (h TodoCrudHandlerV0) GetCreateInput() interface{} { - return &CreateInput{} -} - -// snippet-end: create input - // snippet-start: transform create -func (h TodoCrudHandlerV0) TransformCreate(ctx context.Context, input interface{}, model db_repo.ModelBased) error { - in := input.(*CreateInput) - m := model.(*Todo) - - m.Text = in.Text - m.DueDate = in.DueDate +func (h TodoCrudHandlerV0) TransformCreate(ctx context.Context, in *CreateInput) (*Todo, error) { + m := &Todo{ + Text: in.Text, + DueDate: in.DueDate, + } - return nil + return m, nil } // snippet-end: transform create -// snippet-start: get update input -func (h TodoCrudHandlerV0) GetUpdateInput() interface{} { - return &UpdateInput{} -} - -// snippet-end: get update input - // snippet-start: transform update -func (h TodoCrudHandlerV0) TransformUpdate(ctx context.Context, input interface{}, model db_repo.ModelBased) error { - in := input.(*UpdateInput) - m := model.(*Todo) - +func (h TodoCrudHandlerV0) TransformUpdate(ctx context.Context, in *UpdateInput, m *Todo) (*Todo, error) { m.Text = in.Text - return nil + return m, nil } // snippet-end: transform update // snippet-start: transform output -func (h TodoCrudHandlerV0) TransformOutput(ctx context.Context, model db_repo.ModelBased, apiView string) (interface{}, error) { +func (h TodoCrudHandlerV0) TransformOutput(ctx context.Context, model *Todo, apiView string) (*Todo, error) { return model, nil } // snippet-end: transform output // snippet-start: list -func (h TodoCrudHandlerV0) List(ctx context.Context, qb *db_repo.QueryBuilder, apiView string) (interface{}, error) { +func (h TodoCrudHandlerV0) List(ctx context.Context, qb *db_repo.QueryBuilder, apiView string) ([]*Todo, error) { var err error - - // Instatiate a list of Todo objects, called result. - result := make([]*Todo, 0) + var result []*Todo // Query the database using a Context and a QueryBuilder. If it finds the results, it sets them on result. Otherwise, it returns an error. - if err = h.repo.Query(ctx, qb, &result); err != nil { + if result, err = h.repo.Query(ctx, qb); err != nil { return nil, fmt.Errorf("can not query todo items: %w", err) } // Transform each result with TransformOutput(). - out := make([]interface{}, len(result)) + out := make([]*Todo, len(result)) for i, res := range result { if out[i], err = h.TransformOutput(ctx, res, apiView); err != nil { return nil, err diff --git a/docs/docs/quickstart/http-server/src/write-crud-sql-app/main.go b/docs/docs/quickstart/http-server/src/write-crud-sql-app/main.go index d1a9ab6d9..ed8f2c823 100644 --- a/docs/docs/quickstart/http-server/src/write-crud-sql-app/main.go +++ b/docs/docs/quickstart/http-server/src/write-crud-sql-app/main.go @@ -21,7 +21,7 @@ func main() { def := &httpserver.Definitions{} var err error - var handler crud.Handler + var handler crud.Handler[CreateInput, UpdateInput, *Todo, uint, *Todo] // Created a new CRUD handler. if handler, err = NewTodoCrudHandler(ctx, config, logger); err != nil { diff --git a/examples/apiserver/simple-handlers/entity.go b/examples/apiserver/simple-handlers/entity.go index 58bd4fbea..569347e53 100644 --- a/examples/apiserver/simple-handlers/entity.go +++ b/examples/apiserver/simple-handlers/entity.go @@ -2,9 +2,10 @@ package main import ( "context" + "fmt" "time" - db_repo "github.com/justtrackio/gosoline/pkg/db-repo" + "github.com/justtrackio/gosoline/pkg/db-repo" ) type MyEntity struct { @@ -19,6 +20,14 @@ func (e *MyEntity) GetId() *uint { return &e.Id } +func (e *MyEntity) GetUpdatedAt() *time.Time { + return e.UpdatedAt +} + +func (e *MyEntity) GetCreatedAt() *time.Time { + return e.CreatedAt +} + func (e *MyEntity) SetUpdatedAt(updatedAt *time.Time) { e.UpdatedAt = updatedAt } @@ -29,40 +38,59 @@ func (e *MyEntity) SetCreatedAt(createdAt *time.Time) { type MyEntityRepository struct{} -func (*MyEntityRepository) Create(ctx context.Context, value db_repo.ModelBased) error { +func (*MyEntityRepository) Create(ctx context.Context, value *MyEntity) error { return nil } -func (*MyEntityRepository) Read(ctx context.Context, id *uint, out db_repo.ModelBased) error { - return nil +func (*MyEntityRepository) Read(ctx context.Context, id uint) (*MyEntity, error) { + if id == 1 { + return &MyEntity{ + Id: 1, + Prop1: "text", + }, nil + } + + if id == 2 { + return &MyEntity{ + Id: 2, + Prop2: "text", + }, nil + } + + return nil, db_repo.NewRecordNotFoundError(fmt.Sprintf("%d", id), "myEntity", fmt.Errorf("not found")) } -func (*MyEntityRepository) Update(ctx context.Context, value db_repo.ModelBased) error { +func (*MyEntityRepository) Update(ctx context.Context, value *MyEntity) error { return nil } -func (*MyEntityRepository) Delete(ctx context.Context, value db_repo.ModelBased) error { +func (*MyEntityRepository) Delete(ctx context.Context, value *MyEntity) error { return nil } -func (*MyEntityRepository) Query(ctx context.Context, qb *db_repo.QueryBuilder, result interface{}) error { - r := result.(*[]*MyEntity) +func (*MyEntityRepository) Query(ctx context.Context, qb *db_repo.QueryBuilder) ([]*MyEntity, error) { + return []*MyEntity{ + { + Id: 1, + Prop1: "text", + }, + { + Id: 2, + Prop2: "text", + }, + }, nil +} - *r = append(*r, &MyEntity{ - Id: 1, - Prop1: "text", - }) - *r = append(*r, &MyEntity{ - Id: 2, - Prop1: "text", - }) - result = r +func (*MyEntityRepository) Count(ctx context.Context, qb *db_repo.QueryBuilder) (int, error) { + return 2, nil +} - return nil +func (r *MyEntityRepository) GetModelId() string { + return "project.family.name.MyEntity" } -func (*MyEntityRepository) Count(ctx context.Context, qb *db_repo.QueryBuilder, model db_repo.ModelBased) (int, error) { - return 2, nil +func (r *MyEntityRepository) GetModelName() string { + return "MyEntity" } func (*MyEntityRepository) GetMetadata() db_repo.Metadata { diff --git a/examples/apiserver/simple-handlers/handlers.go b/examples/apiserver/simple-handlers/handlers.go index 1a7e70acb..8a58cb0e2 100644 --- a/examples/apiserver/simple-handlers/handlers.go +++ b/examples/apiserver/simple-handlers/handlers.go @@ -6,7 +6,6 @@ import ( "github.com/justtrackio/gosoline/pkg/db-repo" "github.com/justtrackio/gosoline/pkg/httpserver" - "github.com/justtrackio/gosoline/pkg/httpserver/crud" ) type JsonResponseFromMapHandler struct{} @@ -60,7 +59,7 @@ func (h *AdminAuthenticatedHandler) Handle(requestContext context.Context, reque } type MyEntityHandler struct { - repo crud.Repository + repo db_repo.Repository[uint, *MyEntity] } type MyEntityCreateInput struct { @@ -72,50 +71,29 @@ type MyEntityUpdateInput struct { Prop1 string `json:"prop1"` } -func (h *MyEntityHandler) GetRepository() crud.Repository { +func (h *MyEntityHandler) GetRepository() db_repo.Repository[uint, *MyEntity] { return h.repo } -func (h *MyEntityHandler) GetModel() db_repo.ModelBased { - return &MyEntity{} -} - -func (h *MyEntityHandler) TransformOutput(_ context.Context, model db_repo.ModelBased, apiView string) (output interface{}, err error) { +func (h *MyEntityHandler) TransformOutput(_ context.Context, model *MyEntity, apiView string) (output *MyEntity, err error) { return model, nil } -func (h *MyEntityHandler) GetCreateInput() interface{} { - return &MyEntityCreateInput{} +func (h *MyEntityHandler) TransformCreate(_ context.Context, input *MyEntityCreateInput) (model *MyEntity, err error) { + return &MyEntity{ + Prop1: input.Prop1, + Prop2: input.Prop2, + }, nil } -func (h *MyEntityHandler) TransformCreate(_ context.Context, input interface{}, model db_repo.ModelBased) (err error) { - i := input.(*MyEntityCreateInput) - b := model.(*MyEntity) - - b.Prop1 = i.Prop1 - b.Prop2 = i.Prop2 +func (h *MyEntityHandler) TransformUpdate(_ context.Context, input *MyEntityUpdateInput, model *MyEntity) (updated *MyEntity, err error) { + model.Prop1 = input.Prop1 - return -} - -func (h *MyEntityHandler) GetUpdateInput() interface{} { - return &MyEntityUpdateInput{} -} - -func (h *MyEntityHandler) TransformUpdate(_ context.Context, input interface{}, model db_repo.ModelBased) (err error) { - i := input.(*MyEntityUpdateInput) - b := model.(*MyEntity) - - b.Prop1 = i.Prop1 - - return + return model, nil } -func (h *MyEntityHandler) List(ctx context.Context, qb *db_repo.QueryBuilder, apiView string) (out interface{}, err error) { - res := make([]*MyEntity, 0) - err = h.repo.Query(ctx, qb, &res) - - return res, err +func (h *MyEntityHandler) List(ctx context.Context, qb *db_repo.QueryBuilder, apiView string) (out []*MyEntity, err error) { + return h.repo.Query(ctx, qb) } func (h *MyEntityHandler) Handle(requestContext context.Context, request *httpserver.Request) (response *httpserver.Response, err error) { diff --git a/examples/apiserver/simple-handlers/main.go b/examples/apiserver/simple-handlers/main.go index 7f1235eca..31aa176fb 100644 --- a/examples/apiserver/simple-handlers/main.go +++ b/examples/apiserver/simple-handlers/main.go @@ -37,7 +37,7 @@ func apiDefiner(ctx context.Context, config cfg.Config, logger log.Logger) (*htt group.GET("/authenticated", httpserver.CreateHandler(&AdminAuthenticatedHandler{})) - crud.AddCrudHandlers(logger, definitions, 0, "/myEntity", &MyEntityHandler{ + crud.AddCrudHandlers[MyEntityCreateInput, MyEntityUpdateInput, *MyEntity, uint, *MyEntity](logger, definitions, 0, "/myEntity", &MyEntityHandler{ repo: &MyEntityRepository{}, }) diff --git a/examples/integration/main.go b/examples/integration/main.go index 8c2aa0705..e41fb8614 100644 --- a/examples/integration/main.go +++ b/examples/integration/main.go @@ -26,6 +26,14 @@ func (i *item) GetId() *uint { return &i.Id } +func (i *item) GetUpdatedAt() *time.Time { + return &i.UpdatedAt +} + +func (i *item) GetCreatedAt() *time.Time { + return &i.UpdatedAt +} + func (i *item) SetUpdatedAt(updatedAt *time.Time) { i.UpdatedAt = mdl.EmptyIfNil(updatedAt) } @@ -45,7 +53,8 @@ var ddbSettings = &ddb.Settings{ var repoSettings = db_repo.Settings{ AppId: cfg.AppId{}, Metadata: db_repo.Metadata{ - TableName: "items", + TableName: "items", + PrimaryKey: "items.id", }, } @@ -53,7 +62,7 @@ type app struct { kernel.EssentialModule kernel.ServiceStage ddbRepository ddb.Repository - dbRepository db_repo.Repository + dbRepository db_repo.Repository[uint, *item] } func newAppModule(ctx context.Context, config cfg.Config, logger log.Logger) (kernel.Module, error) { @@ -62,7 +71,7 @@ func newAppModule(ctx context.Context, config cfg.Config, logger log.Logger) (ke return nil, fmt.Errorf("unable to create dynamodb repository: %w", err) } - dbRepository, err := db_repo.New(config, logger, repoSettings) + dbRepository, err := db_repo.New[uint, *item](config, logger, repoSettings) if err != nil { return nil, fmt.Errorf("unable to create mysql client: %w", err) } diff --git a/pkg/application/options.go b/pkg/application/options.go index 9328ae853..120847fd3 100644 --- a/pkg/application/options.go +++ b/pkg/application/options.go @@ -8,7 +8,7 @@ import ( "github.com/justtrackio/gosoline/pkg/cfg" "github.com/justtrackio/gosoline/pkg/clock" - db_repo "github.com/justtrackio/gosoline/pkg/db-repo" + dbRepo "github.com/justtrackio/gosoline/pkg/db-repo" "github.com/justtrackio/gosoline/pkg/exec" "github.com/justtrackio/gosoline/pkg/fixtures" "github.com/justtrackio/gosoline/pkg/httpserver" @@ -137,7 +137,7 @@ func WithExecBackoffSettings(settings *exec.BackoffSettings) Option { func WithDbRepoChangeHistory(app *App) { app.addKernelOption(func(config cfg.GosoConf) kernelPkg.Option { - return kernelPkg.WithMiddlewareFactory(db_repo.KernelMiddlewareChangeHistory, kernelPkg.PositionEnd) + return kernelPkg.WithMiddlewareFactory(dbRepo.KernelMiddlewareChangeHistory, kernelPkg.PositionEnd) }) } diff --git a/pkg/blob/service.go b/pkg/blob/service.go index a5d64a079..8baa8c1de 100644 --- a/pkg/blob/service.go +++ b/pkg/blob/service.go @@ -4,14 +4,13 @@ import ( "context" "fmt" - "github.com/justtrackio/gosoline/pkg/funk" - "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/s3" "github.com/aws/aws-sdk-go-v2/service/s3/types" "github.com/hashicorp/go-multierror" "github.com/justtrackio/gosoline/pkg/cfg" gosoS3 "github.com/justtrackio/gosoline/pkg/cloud/aws/s3" + "github.com/justtrackio/gosoline/pkg/funk" "github.com/justtrackio/gosoline/pkg/log" ) diff --git a/pkg/cloud/aws/awsv2_middleware_retry.go b/pkg/cloud/aws/awsv2_middleware_retry.go index 27166c156..7bb826ecb 100644 --- a/pkg/cloud/aws/awsv2_middleware_retry.go +++ b/pkg/cloud/aws/awsv2_middleware_retry.go @@ -5,13 +5,12 @@ import ( "errors" "time" - "github.com/justtrackio/gosoline/pkg/exec" - "github.com/justtrackio/gosoline/pkg/uuid" - awsMiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" awsRetry "github.com/aws/aws-sdk-go-v2/aws/retry" smithyMiddleware "github.com/aws/smithy-go/middleware" + "github.com/justtrackio/gosoline/pkg/exec" "github.com/justtrackio/gosoline/pkg/log" + "github.com/justtrackio/gosoline/pkg/uuid" ) type ( diff --git a/pkg/cloud/aws/kinesis/kinsumer.go b/pkg/cloud/aws/kinesis/kinsumer.go index 338973db3..6cbc1ab74 100644 --- a/pkg/cloud/aws/kinesis/kinsumer.go +++ b/pkg/cloud/aws/kinesis/kinsumer.go @@ -279,6 +279,7 @@ func (k *kinsumer) refreshShards(ctx context.Context, runtimeCtx *runtimeContext for idx := range shardIds { if shardIds[idx] != runtimeCtx.shardIds[idx] { changed = true + break } } diff --git a/pkg/cloud/aws/kinesis/record_writer.go b/pkg/cloud/aws/kinesis/record_writer.go index cfc66031c..06e76d6ed 100644 --- a/pkg/cloud/aws/kinesis/record_writer.go +++ b/pkg/cloud/aws/kinesis/record_writer.go @@ -5,8 +5,6 @@ import ( "fmt" "strings" - "github.com/justtrackio/gosoline/pkg/funk" - "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/kinesis" "github.com/aws/aws-sdk-go-v2/service/kinesis/types" @@ -15,6 +13,7 @@ import ( "github.com/justtrackio/gosoline/pkg/cfg" "github.com/justtrackio/gosoline/pkg/clock" "github.com/justtrackio/gosoline/pkg/exec" + "github.com/justtrackio/gosoline/pkg/funk" "github.com/justtrackio/gosoline/pkg/log" "github.com/justtrackio/gosoline/pkg/metric" "github.com/justtrackio/gosoline/pkg/uuid" @@ -178,6 +177,7 @@ func (w *recordWriter) putRecordsBatch(ctx context.Context, batch []*Record) err if len(failedRecords) == 0 && attempt > 1 { logger.Warn("PutRecords successful after %d attempts in %s", attempt, took) + break } diff --git a/pkg/db-repo/change_history.go b/pkg/db-repo/change_history.go index 568b58d91..fd9c56d5d 100644 --- a/pkg/db-repo/change_history.go +++ b/pkg/db-repo/change_history.go @@ -70,7 +70,7 @@ func (c *ChangeHistoryModel) GetHistoryAuthorId() int { return c.ChangeHistoryAuthorId } -func MigrateChangeHistory(ctx context.Context, config cfg.Config, logger log.Logger, models ...ModelBased) error { +func MigrateChangeHistory(ctx context.Context, config cfg.Config, logger log.Logger, models ...ModelBased[uint]) error { var err error var manager *ChangeHistoryManager diff --git a/pkg/db-repo/change_history_manager.go b/pkg/db-repo/change_history_manager.go index 878364afd..07d3d85bb 100644 --- a/pkg/db-repo/change_history_manager.go +++ b/pkg/db-repo/change_history_manager.go @@ -23,7 +23,7 @@ type ChangeHistoryManager struct { orm *gorm.DB logger log.Logger settings *changeHistoryManagerSettings - models []ModelBased + models []ModelBased[uint] } type changeHistoryManagerAppCtxKey int @@ -50,7 +50,7 @@ func NewChangeHistoryManager(config cfg.Config, logger log.Logger) (*ChangeHisto }, nil } -func (c *ChangeHistoryManager) addModels(models ...ModelBased) { +func (c *ChangeHistoryManager) addModels(models ...ModelBased[uint]) { c.models = append(c.models, models...) } @@ -75,7 +75,7 @@ func (c *ChangeHistoryManager) RunMigrations() error { return cfn.Wait() } -func (c *ChangeHistoryManager) RunMigration(model ModelBased) error { +func (c *ChangeHistoryManager) RunMigration(model ModelBased[uint]) error { originalTable := c.buildOriginalTableMetadata(model) historyTable := c.buildHistoryTableMetadata(model, originalTable) @@ -158,6 +158,7 @@ func (c *ChangeHistoryManager) executeMigration(originalTable, historyTable *tab statements = append(statements, c.dropHistoryTriggers(originalTable, historyTable)...) statements = append(statements, c.createHistoryTriggers(originalTable, historyTable)...) c.logger.Info("creating change history setup") + return c.execute(statements) } @@ -167,6 +168,7 @@ func (c *ChangeHistoryManager) executeMigration(originalTable, historyTable *tab statements = append(statements, c.dropHistoryTriggers(originalTable, historyTable)...) statements = append(statements, c.createHistoryTriggers(originalTable, historyTable)...) c.logger.Info("updating change history setup") + return c.execute(statements) } @@ -175,7 +177,7 @@ func (c *ChangeHistoryManager) executeMigration(originalTable, historyTable *tab return nil } -func (c *ChangeHistoryManager) buildOriginalTableMetadata(model ModelBased) *tableMetadata { +func (c *ChangeHistoryManager) buildOriginalTableMetadata(model ModelBased[uint]) *tableMetadata { scope := c.orm.NewScope(model) fields := scope.GetModelStruct().StructFields tableName := scope.TableName() @@ -183,7 +185,7 @@ func (c *ChangeHistoryManager) buildOriginalTableMetadata(model ModelBased) *tab return newTableMetadata(scope, tableName, fields) } -func (c *ChangeHistoryManager) buildHistoryTableMetadata(model ModelBased, originalTable *tableMetadata) *tableMetadata { +func (c *ChangeHistoryManager) buildHistoryTableMetadata(model ModelBased[uint], originalTable *tableMetadata) *tableMetadata { historyScope := c.orm.NewScope(ChangeHistoryModel{}) tableName := fmt.Sprintf("%s_%s", originalTable.tableName, c.settings.TableSuffix) modelFields := funk.Filter(c.orm.NewScope(model).GetModelStruct().StructFields, func(field *gorm.StructField) bool { @@ -286,6 +288,7 @@ func (c *ChangeHistoryManager) primaryKeysMatchCondition(originalTable *tableMet condition := fmt.Sprintf("d.%s = %s.%s", columnName, record, columnName) conditions = append(conditions, condition) } + return strings.Join(conditions, " AND ") } @@ -296,6 +299,7 @@ func (c *ChangeHistoryManager) rowUpdatedCondition(originalTable *tableMetadata) condition := fmt.Sprintf("NOT (OLD.%s <=> NEW.%s)", columnName, columnName) conditions = append(conditions, condition) } + return strings.Join(conditions, " OR ") } diff --git a/pkg/db-repo/change_history_metadata.go b/pkg/db-repo/change_history_metadata.go index 1ee05169b..05840618b 100644 --- a/pkg/db-repo/change_history_metadata.go +++ b/pkg/db-repo/change_history_metadata.go @@ -36,6 +36,7 @@ func (m *tableMetadataBuilder) build() *tableMetadata { metadata.tableNameQuoted = m.scope.Quote(m.tableName) metadata.columns = m.buildColumns() metadata.primaryKeys = m.buildPrimaryKeys() + return metadata } @@ -46,6 +47,7 @@ func (m *tableMetadataBuilder) buildColumns() []columnMetadata { columns = append(columns, m.buildColumn(field)) } } + return columns } @@ -56,6 +58,7 @@ func (m *tableMetadataBuilder) buildPrimaryKeys() []columnMetadata { columns = append(columns, m.buildColumn(field)) } } + return columns } @@ -101,6 +104,7 @@ func newTableMetadata(scope *gorm.Scope, tableName string, fields []*gorm.Struct scope: scope, fields: fields, } + return builder.build() } diff --git a/pkg/db-repo/change_history_middleware.go b/pkg/db-repo/change_history_middleware.go index 6604c9295..fa235c5e6 100644 --- a/pkg/db-repo/change_history_middleware.go +++ b/pkg/db-repo/change_history_middleware.go @@ -21,6 +21,7 @@ func KernelMiddlewareChangeHistory(ctx context.Context, config cfg.Config, logge return func() { if err = manager.RunMigrations(); err != nil { logger.Error("can not run change history migrations: %w", err) + return } diff --git a/pkg/db-repo/errors.go b/pkg/db-repo/errors.go index 18b8ac972..d8d0b0842 100644 --- a/pkg/db-repo/errors.go +++ b/pkg/db-repo/errors.go @@ -6,12 +6,12 @@ import ( ) type RecordNotFoundError struct { - id uint + id string modelId string err error } -func NewRecordNotFoundError(id uint, modelId string, err error) RecordNotFoundError { +func NewRecordNotFoundError(id string, modelId string, err error) RecordNotFoundError { return RecordNotFoundError{ id: id, modelId: modelId, @@ -20,7 +20,7 @@ func NewRecordNotFoundError(id uint, modelId string, err error) RecordNotFoundEr } func (e RecordNotFoundError) Error() string { - return fmt.Sprintf("could not find model of type %s with id %d: %s", e.modelId, e.id, e.err) + return fmt.Sprintf("could not find model of type %s with id %s: %s", e.modelId, e.id, e.err) } func (e RecordNotFoundError) Unwrap() error { diff --git a/pkg/db-repo/metadata.go b/pkg/db-repo/metadata.go index 15e446550..a26dc08ef 100644 --- a/pkg/db-repo/metadata.go +++ b/pkg/db-repo/metadata.go @@ -1,6 +1,11 @@ package db_repo -import "github.com/justtrackio/gosoline/pkg/mdl" +import ( + "fmt" + "strings" + + "github.com/justtrackio/gosoline/pkg/mdl" +) const ( BoolAnd = "AND" @@ -21,6 +26,16 @@ type Metadata struct { Mappings FieldMappings } +func (m Metadata) PrimaryKeyWithoutTable() string { + parts := strings.Split(m.PrimaryKey, ".") + primaryKey := parts[len(parts)-1] + if primaryKey == "" { + panic(fmt.Errorf("missing primary key for table %q for model %q", m.TableName, m.TableName)) + } + + return primaryKey +} + type FieldMappings map[string]FieldMapping type FieldMappingColumn struct { diff --git a/pkg/db-repo/metric_repo.go b/pkg/db-repo/metric_repo.go index d60a42867..00e13dda6 100644 --- a/pkg/db-repo/metric_repo.go +++ b/pkg/db-repo/metric_repo.go @@ -16,22 +16,22 @@ const ( MetricNameDbAccessLatency = "DbAccessLatency" ) -type metricRepository struct { - Repository +type metricRepository[K mdl.PossibleIdentifier, M ModelBased[K]] struct { + Repository[K, M] output metric.Writer } -func NewMetricRepository(_ cfg.Config, _ log.Logger, repo Repository) *metricRepository { +func NewMetricRepository[K mdl.PossibleIdentifier, M ModelBased[K]](_ cfg.Config, _ log.Logger, repo Repository[K, M]) Repository[K, M] { defaults := getDefaultRepositoryMetrics(repo.GetMetadata().ModelId) output := metric.NewWriter(defaults...) - return &metricRepository{ + return &metricRepository[K, M]{ Repository: repo, output: output, } } -func (r metricRepository) Create(ctx context.Context, value ModelBased) error { +func (r metricRepository[K, M]) Create(ctx context.Context, value M) error { start := time.Now() err := r.Repository.Create(ctx, value) r.writeMetric(Create, err, start) @@ -39,15 +39,15 @@ func (r metricRepository) Create(ctx context.Context, value ModelBased) error { return err } -func (r metricRepository) Read(ctx context.Context, id *uint, out ModelBased) error { +func (r metricRepository[K, M]) Read(ctx context.Context, id K) (M, error) { start := time.Now() - err := r.Repository.Read(ctx, id, out) + result, err := r.Repository.Read(ctx, id) r.writeMetric(Read, err, start) - return err + return result, err } -func (r metricRepository) Update(ctx context.Context, value ModelBased) error { +func (r metricRepository[K, M]) Update(ctx context.Context, value M) error { start := time.Now() err := r.Repository.Update(ctx, value) r.writeMetric(Update, err, start) @@ -55,7 +55,7 @@ func (r metricRepository) Update(ctx context.Context, value ModelBased) error { return err } -func (r metricRepository) Delete(ctx context.Context, value ModelBased) error { +func (r metricRepository[K, M]) Delete(ctx context.Context, value M) error { start := time.Now() err := r.Repository.Delete(ctx, value) r.writeMetric(Delete, err, start) @@ -63,15 +63,15 @@ func (r metricRepository) Delete(ctx context.Context, value ModelBased) error { return err } -func (r metricRepository) Query(ctx context.Context, qb *QueryBuilder, result interface{}) error { +func (r metricRepository[K, M]) Query(ctx context.Context, qb *QueryBuilder) ([]M, error) { start := time.Now() - err := r.Repository.Query(ctx, qb, result) + result, err := r.Repository.Query(ctx, qb) r.writeMetric(Query, err, start) - return err + return result, err } -func (r metricRepository) writeMetric(op string, err error, start time.Time) { +func (r metricRepository[K, M]) writeMetric(op string, err error, start time.Time) { latencyNano := time.Since(start) metricName := MetricNameDbAccessSuccess diff --git a/pkg/db-repo/mocks/ModelBased.go b/pkg/db-repo/mocks/ModelBased.go index 1fd217479..0ffd64a3e 100644 --- a/pkg/db-repo/mocks/ModelBased.go +++ b/pkg/db-repo/mocks/ModelBased.go @@ -3,34 +3,78 @@ package mocks import ( - time "time" - + mdl "github.com/justtrackio/gosoline/pkg/mdl" mock "github.com/stretchr/testify/mock" + + time "time" ) // ModelBased is an autogenerated mock type for the ModelBased type -type ModelBased struct { +type ModelBased[K mdl.PossibleIdentifier] struct { mock.Mock } -type ModelBased_Expecter struct { +type ModelBased_Expecter[K mdl.PossibleIdentifier] struct { mock *mock.Mock } -func (_m *ModelBased) EXPECT() *ModelBased_Expecter { - return &ModelBased_Expecter{mock: &_m.Mock} +func (_m *ModelBased[K]) EXPECT() *ModelBased_Expecter[K] { + return &ModelBased_Expecter[K]{mock: &_m.Mock} +} + +// GetCreatedAt provides a mock function with given fields: +func (_m *ModelBased[K]) GetCreatedAt() *time.Time { + ret := _m.Called() + + var r0 *time.Time + if rf, ok := ret.Get(0).(func() *time.Time); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*time.Time) + } + } + + return r0 +} + +// ModelBased_GetCreatedAt_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetCreatedAt' +type ModelBased_GetCreatedAt_Call[K mdl.PossibleIdentifier] struct { + *mock.Call +} + +// GetCreatedAt is a helper method to define mock.On call +func (_e *ModelBased_Expecter[K]) GetCreatedAt() *ModelBased_GetCreatedAt_Call[K] { + return &ModelBased_GetCreatedAt_Call[K]{Call: _e.mock.On("GetCreatedAt")} +} + +func (_c *ModelBased_GetCreatedAt_Call[K]) Run(run func()) *ModelBased_GetCreatedAt_Call[K] { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *ModelBased_GetCreatedAt_Call[K]) Return(_a0 *time.Time) *ModelBased_GetCreatedAt_Call[K] { + _c.Call.Return(_a0) + return _c +} + +func (_c *ModelBased_GetCreatedAt_Call[K]) RunAndReturn(run func() *time.Time) *ModelBased_GetCreatedAt_Call[K] { + _c.Call.Return(run) + return _c } // GetId provides a mock function with given fields: -func (_m *ModelBased) GetId() *uint { +func (_m *ModelBased[K]) GetId() *K { ret := _m.Called() - var r0 *uint - if rf, ok := ret.Get(0).(func() *uint); ok { + var r0 *K + if rf, ok := ret.Get(0).(func() *K); ok { r0 = rf() } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*uint) + r0 = ret.Get(0).(*K) } } @@ -38,94 +82,137 @@ func (_m *ModelBased) GetId() *uint { } // ModelBased_GetId_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetId' -type ModelBased_GetId_Call struct { +type ModelBased_GetId_Call[K mdl.PossibleIdentifier] struct { *mock.Call } // GetId is a helper method to define mock.On call -func (_e *ModelBased_Expecter) GetId() *ModelBased_GetId_Call { - return &ModelBased_GetId_Call{Call: _e.mock.On("GetId")} +func (_e *ModelBased_Expecter[K]) GetId() *ModelBased_GetId_Call[K] { + return &ModelBased_GetId_Call[K]{Call: _e.mock.On("GetId")} +} + +func (_c *ModelBased_GetId_Call[K]) Run(run func()) *ModelBased_GetId_Call[K] { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *ModelBased_GetId_Call[K]) Return(_a0 *K) *ModelBased_GetId_Call[K] { + _c.Call.Return(_a0) + return _c +} + +func (_c *ModelBased_GetId_Call[K]) RunAndReturn(run func() *K) *ModelBased_GetId_Call[K] { + _c.Call.Return(run) + return _c +} + +// GetUpdatedAt provides a mock function with given fields: +func (_m *ModelBased[K]) GetUpdatedAt() *time.Time { + ret := _m.Called() + + var r0 *time.Time + if rf, ok := ret.Get(0).(func() *time.Time); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*time.Time) + } + } + + return r0 +} + +// ModelBased_GetUpdatedAt_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetUpdatedAt' +type ModelBased_GetUpdatedAt_Call[K mdl.PossibleIdentifier] struct { + *mock.Call +} + +// GetUpdatedAt is a helper method to define mock.On call +func (_e *ModelBased_Expecter[K]) GetUpdatedAt() *ModelBased_GetUpdatedAt_Call[K] { + return &ModelBased_GetUpdatedAt_Call[K]{Call: _e.mock.On("GetUpdatedAt")} } -func (_c *ModelBased_GetId_Call) Run(run func()) *ModelBased_GetId_Call { +func (_c *ModelBased_GetUpdatedAt_Call[K]) Run(run func()) *ModelBased_GetUpdatedAt_Call[K] { _c.Call.Run(func(args mock.Arguments) { run() }) return _c } -func (_c *ModelBased_GetId_Call) Return(_a0 *uint) *ModelBased_GetId_Call { +func (_c *ModelBased_GetUpdatedAt_Call[K]) Return(_a0 *time.Time) *ModelBased_GetUpdatedAt_Call[K] { _c.Call.Return(_a0) return _c } -func (_c *ModelBased_GetId_Call) RunAndReturn(run func() *uint) *ModelBased_GetId_Call { +func (_c *ModelBased_GetUpdatedAt_Call[K]) RunAndReturn(run func() *time.Time) *ModelBased_GetUpdatedAt_Call[K] { _c.Call.Return(run) return _c } // SetCreatedAt provides a mock function with given fields: createdAt -func (_m *ModelBased) SetCreatedAt(createdAt *time.Time) { +func (_m *ModelBased[K]) SetCreatedAt(createdAt *time.Time) { _m.Called(createdAt) } // ModelBased_SetCreatedAt_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetCreatedAt' -type ModelBased_SetCreatedAt_Call struct { +type ModelBased_SetCreatedAt_Call[K mdl.PossibleIdentifier] struct { *mock.Call } // SetCreatedAt is a helper method to define mock.On call // - createdAt *time.Time -func (_e *ModelBased_Expecter) SetCreatedAt(createdAt interface{}) *ModelBased_SetCreatedAt_Call { - return &ModelBased_SetCreatedAt_Call{Call: _e.mock.On("SetCreatedAt", createdAt)} +func (_e *ModelBased_Expecter[K]) SetCreatedAt(createdAt interface{}) *ModelBased_SetCreatedAt_Call[K] { + return &ModelBased_SetCreatedAt_Call[K]{Call: _e.mock.On("SetCreatedAt", createdAt)} } -func (_c *ModelBased_SetCreatedAt_Call) Run(run func(createdAt *time.Time)) *ModelBased_SetCreatedAt_Call { +func (_c *ModelBased_SetCreatedAt_Call[K]) Run(run func(createdAt *time.Time)) *ModelBased_SetCreatedAt_Call[K] { _c.Call.Run(func(args mock.Arguments) { run(args[0].(*time.Time)) }) return _c } -func (_c *ModelBased_SetCreatedAt_Call) Return() *ModelBased_SetCreatedAt_Call { +func (_c *ModelBased_SetCreatedAt_Call[K]) Return() *ModelBased_SetCreatedAt_Call[K] { _c.Call.Return() return _c } -func (_c *ModelBased_SetCreatedAt_Call) RunAndReturn(run func(*time.Time)) *ModelBased_SetCreatedAt_Call { +func (_c *ModelBased_SetCreatedAt_Call[K]) RunAndReturn(run func(*time.Time)) *ModelBased_SetCreatedAt_Call[K] { _c.Call.Return(run) return _c } // SetUpdatedAt provides a mock function with given fields: updatedAt -func (_m *ModelBased) SetUpdatedAt(updatedAt *time.Time) { +func (_m *ModelBased[K]) SetUpdatedAt(updatedAt *time.Time) { _m.Called(updatedAt) } // ModelBased_SetUpdatedAt_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetUpdatedAt' -type ModelBased_SetUpdatedAt_Call struct { +type ModelBased_SetUpdatedAt_Call[K mdl.PossibleIdentifier] struct { *mock.Call } // SetUpdatedAt is a helper method to define mock.On call // - updatedAt *time.Time -func (_e *ModelBased_Expecter) SetUpdatedAt(updatedAt interface{}) *ModelBased_SetUpdatedAt_Call { - return &ModelBased_SetUpdatedAt_Call{Call: _e.mock.On("SetUpdatedAt", updatedAt)} +func (_e *ModelBased_Expecter[K]) SetUpdatedAt(updatedAt interface{}) *ModelBased_SetUpdatedAt_Call[K] { + return &ModelBased_SetUpdatedAt_Call[K]{Call: _e.mock.On("SetUpdatedAt", updatedAt)} } -func (_c *ModelBased_SetUpdatedAt_Call) Run(run func(updatedAt *time.Time)) *ModelBased_SetUpdatedAt_Call { +func (_c *ModelBased_SetUpdatedAt_Call[K]) Run(run func(updatedAt *time.Time)) *ModelBased_SetUpdatedAt_Call[K] { _c.Call.Run(func(args mock.Arguments) { run(args[0].(*time.Time)) }) return _c } -func (_c *ModelBased_SetUpdatedAt_Call) Return() *ModelBased_SetUpdatedAt_Call { +func (_c *ModelBased_SetUpdatedAt_Call[K]) Return() *ModelBased_SetUpdatedAt_Call[K] { _c.Call.Return() return _c } -func (_c *ModelBased_SetUpdatedAt_Call) RunAndReturn(run func(*time.Time)) *ModelBased_SetUpdatedAt_Call { +func (_c *ModelBased_SetUpdatedAt_Call[K]) RunAndReturn(run func(*time.Time)) *ModelBased_SetUpdatedAt_Call[K] { _c.Call.Return(run) return _c } @@ -136,8 +223,8 @@ type mockConstructorTestingTNewModelBased interface { } // NewModelBased creates a new instance of ModelBased. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewModelBased(t mockConstructorTestingTNewModelBased) *ModelBased { - mock := &ModelBased{} +func NewModelBased[K mdl.PossibleIdentifier](t mockConstructorTestingTNewModelBased) *ModelBased[K] { + mock := &ModelBased[K]{} mock.Mock.Test(t) t.Cleanup(func() { mock.AssertExpectations(t) }) diff --git a/pkg/db-repo/mocks/Repository.go b/pkg/db-repo/mocks/Repository.go index b39dee595..889a53a94 100644 --- a/pkg/db-repo/mocks/Repository.go +++ b/pkg/db-repo/mocks/Repository.go @@ -6,39 +6,41 @@ import ( context "context" db_repo "github.com/justtrackio/gosoline/pkg/db-repo" + mdl "github.com/justtrackio/gosoline/pkg/mdl" + mock "github.com/stretchr/testify/mock" ) // Repository is an autogenerated mock type for the Repository type -type Repository struct { +type Repository[K mdl.PossibleIdentifier, M db_repo.ModelBased[K]] struct { mock.Mock } -type Repository_Expecter struct { +type Repository_Expecter[K mdl.PossibleIdentifier, M db_repo.ModelBased[K]] struct { mock *mock.Mock } -func (_m *Repository) EXPECT() *Repository_Expecter { - return &Repository_Expecter{mock: &_m.Mock} +func (_m *Repository[K, M]) EXPECT() *Repository_Expecter[K, M] { + return &Repository_Expecter[K, M]{mock: &_m.Mock} } -// Count provides a mock function with given fields: ctx, qb, model -func (_m *Repository) Count(ctx context.Context, qb *db_repo.QueryBuilder, model db_repo.ModelBased) (int, error) { - ret := _m.Called(ctx, qb, model) +// Count provides a mock function with given fields: ctx, qb +func (_m *Repository[K, M]) Count(ctx context.Context, qb *db_repo.QueryBuilder) (int, error) { + ret := _m.Called(ctx, qb) var r0 int var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *db_repo.QueryBuilder, db_repo.ModelBased) (int, error)); ok { - return rf(ctx, qb, model) + if rf, ok := ret.Get(0).(func(context.Context, *db_repo.QueryBuilder) (int, error)); ok { + return rf(ctx, qb) } - if rf, ok := ret.Get(0).(func(context.Context, *db_repo.QueryBuilder, db_repo.ModelBased) int); ok { - r0 = rf(ctx, qb, model) + if rf, ok := ret.Get(0).(func(context.Context, *db_repo.QueryBuilder) int); ok { + r0 = rf(ctx, qb) } else { r0 = ret.Get(0).(int) } - if rf, ok := ret.Get(1).(func(context.Context, *db_repo.QueryBuilder, db_repo.ModelBased) error); ok { - r1 = rf(ctx, qb, model) + if rf, ok := ret.Get(1).(func(context.Context, *db_repo.QueryBuilder) error); ok { + r1 = rf(ctx, qb) } else { r1 = ret.Error(1) } @@ -47,41 +49,40 @@ func (_m *Repository) Count(ctx context.Context, qb *db_repo.QueryBuilder, model } // Repository_Count_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Count' -type Repository_Count_Call struct { +type Repository_Count_Call[K mdl.PossibleIdentifier, M db_repo.ModelBased[K]] struct { *mock.Call } // Count is a helper method to define mock.On call // - ctx context.Context // - qb *db_repo.QueryBuilder -// - model db_repo.ModelBased -func (_e *Repository_Expecter) Count(ctx interface{}, qb interface{}, model interface{}) *Repository_Count_Call { - return &Repository_Count_Call{Call: _e.mock.On("Count", ctx, qb, model)} +func (_e *Repository_Expecter[K, M]) Count(ctx interface{}, qb interface{}) *Repository_Count_Call[K, M] { + return &Repository_Count_Call[K, M]{Call: _e.mock.On("Count", ctx, qb)} } -func (_c *Repository_Count_Call) Run(run func(ctx context.Context, qb *db_repo.QueryBuilder, model db_repo.ModelBased)) *Repository_Count_Call { +func (_c *Repository_Count_Call[K, M]) Run(run func(ctx context.Context, qb *db_repo.QueryBuilder)) *Repository_Count_Call[K, M] { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(*db_repo.QueryBuilder), args[2].(db_repo.ModelBased)) + run(args[0].(context.Context), args[1].(*db_repo.QueryBuilder)) }) return _c } -func (_c *Repository_Count_Call) Return(_a0 int, _a1 error) *Repository_Count_Call { +func (_c *Repository_Count_Call[K, M]) Return(_a0 int, _a1 error) *Repository_Count_Call[K, M] { _c.Call.Return(_a0, _a1) return _c } -func (_c *Repository_Count_Call) RunAndReturn(run func(context.Context, *db_repo.QueryBuilder, db_repo.ModelBased) (int, error)) *Repository_Count_Call { +func (_c *Repository_Count_Call[K, M]) RunAndReturn(run func(context.Context, *db_repo.QueryBuilder) (int, error)) *Repository_Count_Call[K, M] { _c.Call.Return(run) return _c } // Create provides a mock function with given fields: ctx, value -func (_m *Repository) Create(ctx context.Context, value db_repo.ModelBased) error { +func (_m *Repository[K, M]) Create(ctx context.Context, value M) error { ret := _m.Called(ctx, value) var r0 error - if rf, ok := ret.Get(0).(func(context.Context, db_repo.ModelBased) error); ok { + if rf, ok := ret.Get(0).(func(context.Context, M) error); ok { r0 = rf(ctx, value) } else { r0 = ret.Error(0) @@ -91,40 +92,40 @@ func (_m *Repository) Create(ctx context.Context, value db_repo.ModelBased) erro } // Repository_Create_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Create' -type Repository_Create_Call struct { +type Repository_Create_Call[K mdl.PossibleIdentifier, M db_repo.ModelBased[K]] struct { *mock.Call } // Create is a helper method to define mock.On call // - ctx context.Context -// - value db_repo.ModelBased -func (_e *Repository_Expecter) Create(ctx interface{}, value interface{}) *Repository_Create_Call { - return &Repository_Create_Call{Call: _e.mock.On("Create", ctx, value)} +// - value M +func (_e *Repository_Expecter[K, M]) Create(ctx interface{}, value interface{}) *Repository_Create_Call[K, M] { + return &Repository_Create_Call[K, M]{Call: _e.mock.On("Create", ctx, value)} } -func (_c *Repository_Create_Call) Run(run func(ctx context.Context, value db_repo.ModelBased)) *Repository_Create_Call { +func (_c *Repository_Create_Call[K, M]) Run(run func(ctx context.Context, value M)) *Repository_Create_Call[K, M] { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(db_repo.ModelBased)) + run(args[0].(context.Context), args[1].(M)) }) return _c } -func (_c *Repository_Create_Call) Return(_a0 error) *Repository_Create_Call { +func (_c *Repository_Create_Call[K, M]) Return(_a0 error) *Repository_Create_Call[K, M] { _c.Call.Return(_a0) return _c } -func (_c *Repository_Create_Call) RunAndReturn(run func(context.Context, db_repo.ModelBased) error) *Repository_Create_Call { +func (_c *Repository_Create_Call[K, M]) RunAndReturn(run func(context.Context, M) error) *Repository_Create_Call[K, M] { _c.Call.Return(run) return _c } // Delete provides a mock function with given fields: ctx, value -func (_m *Repository) Delete(ctx context.Context, value db_repo.ModelBased) error { +func (_m *Repository[K, M]) Delete(ctx context.Context, value M) error { ret := _m.Called(ctx, value) var r0 error - if rf, ok := ret.Get(0).(func(context.Context, db_repo.ModelBased) error); ok { + if rf, ok := ret.Get(0).(func(context.Context, M) error); ok { r0 = rf(ctx, value) } else { r0 = ret.Error(0) @@ -134,36 +135,36 @@ func (_m *Repository) Delete(ctx context.Context, value db_repo.ModelBased) erro } // Repository_Delete_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Delete' -type Repository_Delete_Call struct { +type Repository_Delete_Call[K mdl.PossibleIdentifier, M db_repo.ModelBased[K]] struct { *mock.Call } // Delete is a helper method to define mock.On call // - ctx context.Context -// - value db_repo.ModelBased -func (_e *Repository_Expecter) Delete(ctx interface{}, value interface{}) *Repository_Delete_Call { - return &Repository_Delete_Call{Call: _e.mock.On("Delete", ctx, value)} +// - value M +func (_e *Repository_Expecter[K, M]) Delete(ctx interface{}, value interface{}) *Repository_Delete_Call[K, M] { + return &Repository_Delete_Call[K, M]{Call: _e.mock.On("Delete", ctx, value)} } -func (_c *Repository_Delete_Call) Run(run func(ctx context.Context, value db_repo.ModelBased)) *Repository_Delete_Call { +func (_c *Repository_Delete_Call[K, M]) Run(run func(ctx context.Context, value M)) *Repository_Delete_Call[K, M] { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(db_repo.ModelBased)) + run(args[0].(context.Context), args[1].(M)) }) return _c } -func (_c *Repository_Delete_Call) Return(_a0 error) *Repository_Delete_Call { +func (_c *Repository_Delete_Call[K, M]) Return(_a0 error) *Repository_Delete_Call[K, M] { _c.Call.Return(_a0) return _c } -func (_c *Repository_Delete_Call) RunAndReturn(run func(context.Context, db_repo.ModelBased) error) *Repository_Delete_Call { +func (_c *Repository_Delete_Call[K, M]) RunAndReturn(run func(context.Context, M) error) *Repository_Delete_Call[K, M] { _c.Call.Return(run) return _c } // GetMetadata provides a mock function with given fields: -func (_m *Repository) GetMetadata() db_repo.Metadata { +func (_m *Repository[K, M]) GetMetadata() db_repo.Metadata { ret := _m.Called() var r0 db_repo.Metadata @@ -177,34 +178,34 @@ func (_m *Repository) GetMetadata() db_repo.Metadata { } // Repository_GetMetadata_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetMetadata' -type Repository_GetMetadata_Call struct { +type Repository_GetMetadata_Call[K mdl.PossibleIdentifier, M db_repo.ModelBased[K]] struct { *mock.Call } // GetMetadata is a helper method to define mock.On call -func (_e *Repository_Expecter) GetMetadata() *Repository_GetMetadata_Call { - return &Repository_GetMetadata_Call{Call: _e.mock.On("GetMetadata")} +func (_e *Repository_Expecter[K, M]) GetMetadata() *Repository_GetMetadata_Call[K, M] { + return &Repository_GetMetadata_Call[K, M]{Call: _e.mock.On("GetMetadata")} } -func (_c *Repository_GetMetadata_Call) Run(run func()) *Repository_GetMetadata_Call { +func (_c *Repository_GetMetadata_Call[K, M]) Run(run func()) *Repository_GetMetadata_Call[K, M] { _c.Call.Run(func(args mock.Arguments) { run() }) return _c } -func (_c *Repository_GetMetadata_Call) Return(_a0 db_repo.Metadata) *Repository_GetMetadata_Call { +func (_c *Repository_GetMetadata_Call[K, M]) Return(_a0 db_repo.Metadata) *Repository_GetMetadata_Call[K, M] { _c.Call.Return(_a0) return _c } -func (_c *Repository_GetMetadata_Call) RunAndReturn(run func() db_repo.Metadata) *Repository_GetMetadata_Call { +func (_c *Repository_GetMetadata_Call[K, M]) RunAndReturn(run func() db_repo.Metadata) *Repository_GetMetadata_Call[K, M] { _c.Call.Return(run) return _c } // GetModelId provides a mock function with given fields: -func (_m *Repository) GetModelId() string { +func (_m *Repository[K, M]) GetModelId() string { ret := _m.Called() var r0 string @@ -218,34 +219,34 @@ func (_m *Repository) GetModelId() string { } // Repository_GetModelId_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetModelId' -type Repository_GetModelId_Call struct { +type Repository_GetModelId_Call[K mdl.PossibleIdentifier, M db_repo.ModelBased[K]] struct { *mock.Call } // GetModelId is a helper method to define mock.On call -func (_e *Repository_Expecter) GetModelId() *Repository_GetModelId_Call { - return &Repository_GetModelId_Call{Call: _e.mock.On("GetModelId")} +func (_e *Repository_Expecter[K, M]) GetModelId() *Repository_GetModelId_Call[K, M] { + return &Repository_GetModelId_Call[K, M]{Call: _e.mock.On("GetModelId")} } -func (_c *Repository_GetModelId_Call) Run(run func()) *Repository_GetModelId_Call { +func (_c *Repository_GetModelId_Call[K, M]) Run(run func()) *Repository_GetModelId_Call[K, M] { _c.Call.Run(func(args mock.Arguments) { run() }) return _c } -func (_c *Repository_GetModelId_Call) Return(_a0 string) *Repository_GetModelId_Call { +func (_c *Repository_GetModelId_Call[K, M]) Return(_a0 string) *Repository_GetModelId_Call[K, M] { _c.Call.Return(_a0) return _c } -func (_c *Repository_GetModelId_Call) RunAndReturn(run func() string) *Repository_GetModelId_Call { +func (_c *Repository_GetModelId_Call[K, M]) RunAndReturn(run func() string) *Repository_GetModelId_Call[K, M] { _c.Call.Return(run) return _c } // GetModelName provides a mock function with given fields: -func (_m *Repository) GetModelName() string { +func (_m *Repository[K, M]) GetModelName() string { ret := _m.Called() var r0 string @@ -259,126 +260,146 @@ func (_m *Repository) GetModelName() string { } // Repository_GetModelName_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetModelName' -type Repository_GetModelName_Call struct { +type Repository_GetModelName_Call[K mdl.PossibleIdentifier, M db_repo.ModelBased[K]] struct { *mock.Call } // GetModelName is a helper method to define mock.On call -func (_e *Repository_Expecter) GetModelName() *Repository_GetModelName_Call { - return &Repository_GetModelName_Call{Call: _e.mock.On("GetModelName")} +func (_e *Repository_Expecter[K, M]) GetModelName() *Repository_GetModelName_Call[K, M] { + return &Repository_GetModelName_Call[K, M]{Call: _e.mock.On("GetModelName")} } -func (_c *Repository_GetModelName_Call) Run(run func()) *Repository_GetModelName_Call { +func (_c *Repository_GetModelName_Call[K, M]) Run(run func()) *Repository_GetModelName_Call[K, M] { _c.Call.Run(func(args mock.Arguments) { run() }) return _c } -func (_c *Repository_GetModelName_Call) Return(_a0 string) *Repository_GetModelName_Call { +func (_c *Repository_GetModelName_Call[K, M]) Return(_a0 string) *Repository_GetModelName_Call[K, M] { _c.Call.Return(_a0) return _c } -func (_c *Repository_GetModelName_Call) RunAndReturn(run func() string) *Repository_GetModelName_Call { +func (_c *Repository_GetModelName_Call[K, M]) RunAndReturn(run func() string) *Repository_GetModelName_Call[K, M] { _c.Call.Return(run) return _c } -// Query provides a mock function with given fields: ctx, qb, result -func (_m *Repository) Query(ctx context.Context, qb *db_repo.QueryBuilder, result interface{}) error { - ret := _m.Called(ctx, qb, result) +// Query provides a mock function with given fields: ctx, qb +func (_m *Repository[K, M]) Query(ctx context.Context, qb *db_repo.QueryBuilder) ([]M, error) { + ret := _m.Called(ctx, qb) - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, *db_repo.QueryBuilder, interface{}) error); ok { - r0 = rf(ctx, qb, result) + var r0 []M + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *db_repo.QueryBuilder) ([]M, error)); ok { + return rf(ctx, qb) + } + if rf, ok := ret.Get(0).(func(context.Context, *db_repo.QueryBuilder) []M); ok { + r0 = rf(ctx, qb) } else { - r0 = ret.Error(0) + if ret.Get(0) != nil { + r0 = ret.Get(0).([]M) + } } - return r0 + if rf, ok := ret.Get(1).(func(context.Context, *db_repo.QueryBuilder) error); ok { + r1 = rf(ctx, qb) + } else { + r1 = ret.Error(1) + } + + return r0, r1 } // Repository_Query_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Query' -type Repository_Query_Call struct { +type Repository_Query_Call[K mdl.PossibleIdentifier, M db_repo.ModelBased[K]] struct { *mock.Call } // Query is a helper method to define mock.On call // - ctx context.Context // - qb *db_repo.QueryBuilder -// - result interface{} -func (_e *Repository_Expecter) Query(ctx interface{}, qb interface{}, result interface{}) *Repository_Query_Call { - return &Repository_Query_Call{Call: _e.mock.On("Query", ctx, qb, result)} +func (_e *Repository_Expecter[K, M]) Query(ctx interface{}, qb interface{}) *Repository_Query_Call[K, M] { + return &Repository_Query_Call[K, M]{Call: _e.mock.On("Query", ctx, qb)} } -func (_c *Repository_Query_Call) Run(run func(ctx context.Context, qb *db_repo.QueryBuilder, result interface{})) *Repository_Query_Call { +func (_c *Repository_Query_Call[K, M]) Run(run func(ctx context.Context, qb *db_repo.QueryBuilder)) *Repository_Query_Call[K, M] { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(*db_repo.QueryBuilder), args[2].(interface{})) + run(args[0].(context.Context), args[1].(*db_repo.QueryBuilder)) }) return _c } -func (_c *Repository_Query_Call) Return(_a0 error) *Repository_Query_Call { - _c.Call.Return(_a0) +func (_c *Repository_Query_Call[K, M]) Return(_a0 []M, _a1 error) *Repository_Query_Call[K, M] { + _c.Call.Return(_a0, _a1) return _c } -func (_c *Repository_Query_Call) RunAndReturn(run func(context.Context, *db_repo.QueryBuilder, interface{}) error) *Repository_Query_Call { +func (_c *Repository_Query_Call[K, M]) RunAndReturn(run func(context.Context, *db_repo.QueryBuilder) ([]M, error)) *Repository_Query_Call[K, M] { _c.Call.Return(run) return _c } -// Read provides a mock function with given fields: ctx, id, out -func (_m *Repository) Read(ctx context.Context, id *uint, out db_repo.ModelBased) error { - ret := _m.Called(ctx, id, out) +// Read provides a mock function with given fields: ctx, id +func (_m *Repository[K, M]) Read(ctx context.Context, id K) (M, error) { + ret := _m.Called(ctx, id) - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, *uint, db_repo.ModelBased) error); ok { - r0 = rf(ctx, id, out) + var r0 M + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, K) (M, error)); ok { + return rf(ctx, id) + } + if rf, ok := ret.Get(0).(func(context.Context, K) M); ok { + r0 = rf(ctx, id) } else { - r0 = ret.Error(0) + r0 = ret.Get(0).(M) } - return r0 + if rf, ok := ret.Get(1).(func(context.Context, K) error); ok { + r1 = rf(ctx, id) + } else { + r1 = ret.Error(1) + } + + return r0, r1 } // Repository_Read_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Read' -type Repository_Read_Call struct { +type Repository_Read_Call[K mdl.PossibleIdentifier, M db_repo.ModelBased[K]] struct { *mock.Call } // Read is a helper method to define mock.On call // - ctx context.Context -// - id *uint -// - out db_repo.ModelBased -func (_e *Repository_Expecter) Read(ctx interface{}, id interface{}, out interface{}) *Repository_Read_Call { - return &Repository_Read_Call{Call: _e.mock.On("Read", ctx, id, out)} +// - id K +func (_e *Repository_Expecter[K, M]) Read(ctx interface{}, id interface{}) *Repository_Read_Call[K, M] { + return &Repository_Read_Call[K, M]{Call: _e.mock.On("Read", ctx, id)} } -func (_c *Repository_Read_Call) Run(run func(ctx context.Context, id *uint, out db_repo.ModelBased)) *Repository_Read_Call { +func (_c *Repository_Read_Call[K, M]) Run(run func(ctx context.Context, id K)) *Repository_Read_Call[K, M] { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(*uint), args[2].(db_repo.ModelBased)) + run(args[0].(context.Context), args[1].(K)) }) return _c } -func (_c *Repository_Read_Call) Return(_a0 error) *Repository_Read_Call { - _c.Call.Return(_a0) +func (_c *Repository_Read_Call[K, M]) Return(_a0 M, _a1 error) *Repository_Read_Call[K, M] { + _c.Call.Return(_a0, _a1) return _c } -func (_c *Repository_Read_Call) RunAndReturn(run func(context.Context, *uint, db_repo.ModelBased) error) *Repository_Read_Call { +func (_c *Repository_Read_Call[K, M]) RunAndReturn(run func(context.Context, K) (M, error)) *Repository_Read_Call[K, M] { _c.Call.Return(run) return _c } // Update provides a mock function with given fields: ctx, value -func (_m *Repository) Update(ctx context.Context, value db_repo.ModelBased) error { +func (_m *Repository[K, M]) Update(ctx context.Context, value M) error { ret := _m.Called(ctx, value) var r0 error - if rf, ok := ret.Get(0).(func(context.Context, db_repo.ModelBased) error); ok { + if rf, ok := ret.Get(0).(func(context.Context, M) error); ok { r0 = rf(ctx, value) } else { r0 = ret.Error(0) @@ -388,30 +409,30 @@ func (_m *Repository) Update(ctx context.Context, value db_repo.ModelBased) erro } // Repository_Update_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Update' -type Repository_Update_Call struct { +type Repository_Update_Call[K mdl.PossibleIdentifier, M db_repo.ModelBased[K]] struct { *mock.Call } // Update is a helper method to define mock.On call // - ctx context.Context -// - value db_repo.ModelBased -func (_e *Repository_Expecter) Update(ctx interface{}, value interface{}) *Repository_Update_Call { - return &Repository_Update_Call{Call: _e.mock.On("Update", ctx, value)} +// - value M +func (_e *Repository_Expecter[K, M]) Update(ctx interface{}, value interface{}) *Repository_Update_Call[K, M] { + return &Repository_Update_Call[K, M]{Call: _e.mock.On("Update", ctx, value)} } -func (_c *Repository_Update_Call) Run(run func(ctx context.Context, value db_repo.ModelBased)) *Repository_Update_Call { +func (_c *Repository_Update_Call[K, M]) Run(run func(ctx context.Context, value M)) *Repository_Update_Call[K, M] { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(db_repo.ModelBased)) + run(args[0].(context.Context), args[1].(M)) }) return _c } -func (_c *Repository_Update_Call) Return(_a0 error) *Repository_Update_Call { +func (_c *Repository_Update_Call[K, M]) Return(_a0 error) *Repository_Update_Call[K, M] { _c.Call.Return(_a0) return _c } -func (_c *Repository_Update_Call) RunAndReturn(run func(context.Context, db_repo.ModelBased) error) *Repository_Update_Call { +func (_c *Repository_Update_Call[K, M]) RunAndReturn(run func(context.Context, M) error) *Repository_Update_Call[K, M] { _c.Call.Return(run) return _c } @@ -422,8 +443,8 @@ type mockConstructorTestingTNewRepository interface { } // NewRepository creates a new instance of Repository. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewRepository(t mockConstructorTestingTNewRepository) *Repository { - mock := &Repository{} +func NewRepository[K mdl.PossibleIdentifier, M db_repo.ModelBased[K]](t mockConstructorTestingTNewRepository) *Repository[K, M] { + mock := &Repository[K, M]{} mock.Mock.Test(t) t.Cleanup(func() { mock.AssertExpectations(t) }) diff --git a/pkg/db-repo/mocks/RepositoryReadOnly.go b/pkg/db-repo/mocks/RepositoryReadOnly.go index 766c19620..552c174a8 100644 --- a/pkg/db-repo/mocks/RepositoryReadOnly.go +++ b/pkg/db-repo/mocks/RepositoryReadOnly.go @@ -6,39 +6,41 @@ import ( context "context" db_repo "github.com/justtrackio/gosoline/pkg/db-repo" + mdl "github.com/justtrackio/gosoline/pkg/mdl" + mock "github.com/stretchr/testify/mock" ) // RepositoryReadOnly is an autogenerated mock type for the RepositoryReadOnly type -type RepositoryReadOnly struct { +type RepositoryReadOnly[K mdl.PossibleIdentifier, M db_repo.ModelBased[K]] struct { mock.Mock } -type RepositoryReadOnly_Expecter struct { +type RepositoryReadOnly_Expecter[K mdl.PossibleIdentifier, M db_repo.ModelBased[K]] struct { mock *mock.Mock } -func (_m *RepositoryReadOnly) EXPECT() *RepositoryReadOnly_Expecter { - return &RepositoryReadOnly_Expecter{mock: &_m.Mock} +func (_m *RepositoryReadOnly[K, M]) EXPECT() *RepositoryReadOnly_Expecter[K, M] { + return &RepositoryReadOnly_Expecter[K, M]{mock: &_m.Mock} } -// Count provides a mock function with given fields: ctx, qb, model -func (_m *RepositoryReadOnly) Count(ctx context.Context, qb *db_repo.QueryBuilder, model db_repo.ModelBased) (int, error) { - ret := _m.Called(ctx, qb, model) +// Count provides a mock function with given fields: ctx, qb +func (_m *RepositoryReadOnly[K, M]) Count(ctx context.Context, qb *db_repo.QueryBuilder) (int, error) { + ret := _m.Called(ctx, qb) var r0 int var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *db_repo.QueryBuilder, db_repo.ModelBased) (int, error)); ok { - return rf(ctx, qb, model) + if rf, ok := ret.Get(0).(func(context.Context, *db_repo.QueryBuilder) (int, error)); ok { + return rf(ctx, qb) } - if rf, ok := ret.Get(0).(func(context.Context, *db_repo.QueryBuilder, db_repo.ModelBased) int); ok { - r0 = rf(ctx, qb, model) + if rf, ok := ret.Get(0).(func(context.Context, *db_repo.QueryBuilder) int); ok { + r0 = rf(ctx, qb) } else { r0 = ret.Get(0).(int) } - if rf, ok := ret.Get(1).(func(context.Context, *db_repo.QueryBuilder, db_repo.ModelBased) error); ok { - r1 = rf(ctx, qb, model) + if rf, ok := ret.Get(1).(func(context.Context, *db_repo.QueryBuilder) error); ok { + r1 = rf(ctx, qb) } else { r1 = ret.Error(1) } @@ -47,37 +49,36 @@ func (_m *RepositoryReadOnly) Count(ctx context.Context, qb *db_repo.QueryBuilde } // RepositoryReadOnly_Count_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Count' -type RepositoryReadOnly_Count_Call struct { +type RepositoryReadOnly_Count_Call[K mdl.PossibleIdentifier, M db_repo.ModelBased[K]] struct { *mock.Call } // Count is a helper method to define mock.On call // - ctx context.Context // - qb *db_repo.QueryBuilder -// - model db_repo.ModelBased -func (_e *RepositoryReadOnly_Expecter) Count(ctx interface{}, qb interface{}, model interface{}) *RepositoryReadOnly_Count_Call { - return &RepositoryReadOnly_Count_Call{Call: _e.mock.On("Count", ctx, qb, model)} +func (_e *RepositoryReadOnly_Expecter[K, M]) Count(ctx interface{}, qb interface{}) *RepositoryReadOnly_Count_Call[K, M] { + return &RepositoryReadOnly_Count_Call[K, M]{Call: _e.mock.On("Count", ctx, qb)} } -func (_c *RepositoryReadOnly_Count_Call) Run(run func(ctx context.Context, qb *db_repo.QueryBuilder, model db_repo.ModelBased)) *RepositoryReadOnly_Count_Call { +func (_c *RepositoryReadOnly_Count_Call[K, M]) Run(run func(ctx context.Context, qb *db_repo.QueryBuilder)) *RepositoryReadOnly_Count_Call[K, M] { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(*db_repo.QueryBuilder), args[2].(db_repo.ModelBased)) + run(args[0].(context.Context), args[1].(*db_repo.QueryBuilder)) }) return _c } -func (_c *RepositoryReadOnly_Count_Call) Return(_a0 int, _a1 error) *RepositoryReadOnly_Count_Call { +func (_c *RepositoryReadOnly_Count_Call[K, M]) Return(_a0 int, _a1 error) *RepositoryReadOnly_Count_Call[K, M] { _c.Call.Return(_a0, _a1) return _c } -func (_c *RepositoryReadOnly_Count_Call) RunAndReturn(run func(context.Context, *db_repo.QueryBuilder, db_repo.ModelBased) (int, error)) *RepositoryReadOnly_Count_Call { +func (_c *RepositoryReadOnly_Count_Call[K, M]) RunAndReturn(run func(context.Context, *db_repo.QueryBuilder) (int, error)) *RepositoryReadOnly_Count_Call[K, M] { _c.Call.Return(run) return _c } // GetMetadata provides a mock function with given fields: -func (_m *RepositoryReadOnly) GetMetadata() db_repo.Metadata { +func (_m *RepositoryReadOnly[K, M]) GetMetadata() db_repo.Metadata { ret := _m.Called() var r0 db_repo.Metadata @@ -91,34 +92,34 @@ func (_m *RepositoryReadOnly) GetMetadata() db_repo.Metadata { } // RepositoryReadOnly_GetMetadata_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetMetadata' -type RepositoryReadOnly_GetMetadata_Call struct { +type RepositoryReadOnly_GetMetadata_Call[K mdl.PossibleIdentifier, M db_repo.ModelBased[K]] struct { *mock.Call } // GetMetadata is a helper method to define mock.On call -func (_e *RepositoryReadOnly_Expecter) GetMetadata() *RepositoryReadOnly_GetMetadata_Call { - return &RepositoryReadOnly_GetMetadata_Call{Call: _e.mock.On("GetMetadata")} +func (_e *RepositoryReadOnly_Expecter[K, M]) GetMetadata() *RepositoryReadOnly_GetMetadata_Call[K, M] { + return &RepositoryReadOnly_GetMetadata_Call[K, M]{Call: _e.mock.On("GetMetadata")} } -func (_c *RepositoryReadOnly_GetMetadata_Call) Run(run func()) *RepositoryReadOnly_GetMetadata_Call { +func (_c *RepositoryReadOnly_GetMetadata_Call[K, M]) Run(run func()) *RepositoryReadOnly_GetMetadata_Call[K, M] { _c.Call.Run(func(args mock.Arguments) { run() }) return _c } -func (_c *RepositoryReadOnly_GetMetadata_Call) Return(_a0 db_repo.Metadata) *RepositoryReadOnly_GetMetadata_Call { +func (_c *RepositoryReadOnly_GetMetadata_Call[K, M]) Return(_a0 db_repo.Metadata) *RepositoryReadOnly_GetMetadata_Call[K, M] { _c.Call.Return(_a0) return _c } -func (_c *RepositoryReadOnly_GetMetadata_Call) RunAndReturn(run func() db_repo.Metadata) *RepositoryReadOnly_GetMetadata_Call { +func (_c *RepositoryReadOnly_GetMetadata_Call[K, M]) RunAndReturn(run func() db_repo.Metadata) *RepositoryReadOnly_GetMetadata_Call[K, M] { _c.Call.Return(run) return _c } // GetModelId provides a mock function with given fields: -func (_m *RepositoryReadOnly) GetModelId() string { +func (_m *RepositoryReadOnly[K, M]) GetModelId() string { ret := _m.Called() var r0 string @@ -132,34 +133,34 @@ func (_m *RepositoryReadOnly) GetModelId() string { } // RepositoryReadOnly_GetModelId_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetModelId' -type RepositoryReadOnly_GetModelId_Call struct { +type RepositoryReadOnly_GetModelId_Call[K mdl.PossibleIdentifier, M db_repo.ModelBased[K]] struct { *mock.Call } // GetModelId is a helper method to define mock.On call -func (_e *RepositoryReadOnly_Expecter) GetModelId() *RepositoryReadOnly_GetModelId_Call { - return &RepositoryReadOnly_GetModelId_Call{Call: _e.mock.On("GetModelId")} +func (_e *RepositoryReadOnly_Expecter[K, M]) GetModelId() *RepositoryReadOnly_GetModelId_Call[K, M] { + return &RepositoryReadOnly_GetModelId_Call[K, M]{Call: _e.mock.On("GetModelId")} } -func (_c *RepositoryReadOnly_GetModelId_Call) Run(run func()) *RepositoryReadOnly_GetModelId_Call { +func (_c *RepositoryReadOnly_GetModelId_Call[K, M]) Run(run func()) *RepositoryReadOnly_GetModelId_Call[K, M] { _c.Call.Run(func(args mock.Arguments) { run() }) return _c } -func (_c *RepositoryReadOnly_GetModelId_Call) Return(_a0 string) *RepositoryReadOnly_GetModelId_Call { +func (_c *RepositoryReadOnly_GetModelId_Call[K, M]) Return(_a0 string) *RepositoryReadOnly_GetModelId_Call[K, M] { _c.Call.Return(_a0) return _c } -func (_c *RepositoryReadOnly_GetModelId_Call) RunAndReturn(run func() string) *RepositoryReadOnly_GetModelId_Call { +func (_c *RepositoryReadOnly_GetModelId_Call[K, M]) RunAndReturn(run func() string) *RepositoryReadOnly_GetModelId_Call[K, M] { _c.Call.Return(run) return _c } // GetModelName provides a mock function with given fields: -func (_m *RepositoryReadOnly) GetModelName() string { +func (_m *RepositoryReadOnly[K, M]) GetModelName() string { ret := _m.Called() var r0 string @@ -173,116 +174,136 @@ func (_m *RepositoryReadOnly) GetModelName() string { } // RepositoryReadOnly_GetModelName_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetModelName' -type RepositoryReadOnly_GetModelName_Call struct { +type RepositoryReadOnly_GetModelName_Call[K mdl.PossibleIdentifier, M db_repo.ModelBased[K]] struct { *mock.Call } // GetModelName is a helper method to define mock.On call -func (_e *RepositoryReadOnly_Expecter) GetModelName() *RepositoryReadOnly_GetModelName_Call { - return &RepositoryReadOnly_GetModelName_Call{Call: _e.mock.On("GetModelName")} +func (_e *RepositoryReadOnly_Expecter[K, M]) GetModelName() *RepositoryReadOnly_GetModelName_Call[K, M] { + return &RepositoryReadOnly_GetModelName_Call[K, M]{Call: _e.mock.On("GetModelName")} } -func (_c *RepositoryReadOnly_GetModelName_Call) Run(run func()) *RepositoryReadOnly_GetModelName_Call { +func (_c *RepositoryReadOnly_GetModelName_Call[K, M]) Run(run func()) *RepositoryReadOnly_GetModelName_Call[K, M] { _c.Call.Run(func(args mock.Arguments) { run() }) return _c } -func (_c *RepositoryReadOnly_GetModelName_Call) Return(_a0 string) *RepositoryReadOnly_GetModelName_Call { +func (_c *RepositoryReadOnly_GetModelName_Call[K, M]) Return(_a0 string) *RepositoryReadOnly_GetModelName_Call[K, M] { _c.Call.Return(_a0) return _c } -func (_c *RepositoryReadOnly_GetModelName_Call) RunAndReturn(run func() string) *RepositoryReadOnly_GetModelName_Call { +func (_c *RepositoryReadOnly_GetModelName_Call[K, M]) RunAndReturn(run func() string) *RepositoryReadOnly_GetModelName_Call[K, M] { _c.Call.Return(run) return _c } -// Query provides a mock function with given fields: ctx, qb, result -func (_m *RepositoryReadOnly) Query(ctx context.Context, qb *db_repo.QueryBuilder, result interface{}) error { - ret := _m.Called(ctx, qb, result) +// Query provides a mock function with given fields: ctx, qb +func (_m *RepositoryReadOnly[K, M]) Query(ctx context.Context, qb *db_repo.QueryBuilder) ([]M, error) { + ret := _m.Called(ctx, qb) - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, *db_repo.QueryBuilder, interface{}) error); ok { - r0 = rf(ctx, qb, result) + var r0 []M + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *db_repo.QueryBuilder) ([]M, error)); ok { + return rf(ctx, qb) + } + if rf, ok := ret.Get(0).(func(context.Context, *db_repo.QueryBuilder) []M); ok { + r0 = rf(ctx, qb) } else { - r0 = ret.Error(0) + if ret.Get(0) != nil { + r0 = ret.Get(0).([]M) + } } - return r0 + if rf, ok := ret.Get(1).(func(context.Context, *db_repo.QueryBuilder) error); ok { + r1 = rf(ctx, qb) + } else { + r1 = ret.Error(1) + } + + return r0, r1 } // RepositoryReadOnly_Query_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Query' -type RepositoryReadOnly_Query_Call struct { +type RepositoryReadOnly_Query_Call[K mdl.PossibleIdentifier, M db_repo.ModelBased[K]] struct { *mock.Call } // Query is a helper method to define mock.On call // - ctx context.Context // - qb *db_repo.QueryBuilder -// - result interface{} -func (_e *RepositoryReadOnly_Expecter) Query(ctx interface{}, qb interface{}, result interface{}) *RepositoryReadOnly_Query_Call { - return &RepositoryReadOnly_Query_Call{Call: _e.mock.On("Query", ctx, qb, result)} +func (_e *RepositoryReadOnly_Expecter[K, M]) Query(ctx interface{}, qb interface{}) *RepositoryReadOnly_Query_Call[K, M] { + return &RepositoryReadOnly_Query_Call[K, M]{Call: _e.mock.On("Query", ctx, qb)} } -func (_c *RepositoryReadOnly_Query_Call) Run(run func(ctx context.Context, qb *db_repo.QueryBuilder, result interface{})) *RepositoryReadOnly_Query_Call { +func (_c *RepositoryReadOnly_Query_Call[K, M]) Run(run func(ctx context.Context, qb *db_repo.QueryBuilder)) *RepositoryReadOnly_Query_Call[K, M] { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(*db_repo.QueryBuilder), args[2].(interface{})) + run(args[0].(context.Context), args[1].(*db_repo.QueryBuilder)) }) return _c } -func (_c *RepositoryReadOnly_Query_Call) Return(_a0 error) *RepositoryReadOnly_Query_Call { - _c.Call.Return(_a0) +func (_c *RepositoryReadOnly_Query_Call[K, M]) Return(_a0 []M, _a1 error) *RepositoryReadOnly_Query_Call[K, M] { + _c.Call.Return(_a0, _a1) return _c } -func (_c *RepositoryReadOnly_Query_Call) RunAndReturn(run func(context.Context, *db_repo.QueryBuilder, interface{}) error) *RepositoryReadOnly_Query_Call { +func (_c *RepositoryReadOnly_Query_Call[K, M]) RunAndReturn(run func(context.Context, *db_repo.QueryBuilder) ([]M, error)) *RepositoryReadOnly_Query_Call[K, M] { _c.Call.Return(run) return _c } -// Read provides a mock function with given fields: ctx, id, out -func (_m *RepositoryReadOnly) Read(ctx context.Context, id *uint, out db_repo.ModelBased) error { - ret := _m.Called(ctx, id, out) +// Read provides a mock function with given fields: ctx, id +func (_m *RepositoryReadOnly[K, M]) Read(ctx context.Context, id K) (M, error) { + ret := _m.Called(ctx, id) - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, *uint, db_repo.ModelBased) error); ok { - r0 = rf(ctx, id, out) + var r0 M + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, K) (M, error)); ok { + return rf(ctx, id) + } + if rf, ok := ret.Get(0).(func(context.Context, K) M); ok { + r0 = rf(ctx, id) } else { - r0 = ret.Error(0) + r0 = ret.Get(0).(M) } - return r0 + if rf, ok := ret.Get(1).(func(context.Context, K) error); ok { + r1 = rf(ctx, id) + } else { + r1 = ret.Error(1) + } + + return r0, r1 } // RepositoryReadOnly_Read_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Read' -type RepositoryReadOnly_Read_Call struct { +type RepositoryReadOnly_Read_Call[K mdl.PossibleIdentifier, M db_repo.ModelBased[K]] struct { *mock.Call } // Read is a helper method to define mock.On call // - ctx context.Context -// - id *uint -// - out db_repo.ModelBased -func (_e *RepositoryReadOnly_Expecter) Read(ctx interface{}, id interface{}, out interface{}) *RepositoryReadOnly_Read_Call { - return &RepositoryReadOnly_Read_Call{Call: _e.mock.On("Read", ctx, id, out)} +// - id K +func (_e *RepositoryReadOnly_Expecter[K, M]) Read(ctx interface{}, id interface{}) *RepositoryReadOnly_Read_Call[K, M] { + return &RepositoryReadOnly_Read_Call[K, M]{Call: _e.mock.On("Read", ctx, id)} } -func (_c *RepositoryReadOnly_Read_Call) Run(run func(ctx context.Context, id *uint, out db_repo.ModelBased)) *RepositoryReadOnly_Read_Call { +func (_c *RepositoryReadOnly_Read_Call[K, M]) Run(run func(ctx context.Context, id K)) *RepositoryReadOnly_Read_Call[K, M] { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(*uint), args[2].(db_repo.ModelBased)) + run(args[0].(context.Context), args[1].(K)) }) return _c } -func (_c *RepositoryReadOnly_Read_Call) Return(_a0 error) *RepositoryReadOnly_Read_Call { - _c.Call.Return(_a0) +func (_c *RepositoryReadOnly_Read_Call[K, M]) Return(_a0 M, _a1 error) *RepositoryReadOnly_Read_Call[K, M] { + _c.Call.Return(_a0, _a1) return _c } -func (_c *RepositoryReadOnly_Read_Call) RunAndReturn(run func(context.Context, *uint, db_repo.ModelBased) error) *RepositoryReadOnly_Read_Call { +func (_c *RepositoryReadOnly_Read_Call[K, M]) RunAndReturn(run func(context.Context, K) (M, error)) *RepositoryReadOnly_Read_Call[K, M] { _c.Call.Return(run) return _c } @@ -293,8 +314,8 @@ type mockConstructorTestingTNewRepositoryReadOnly interface { } // NewRepositoryReadOnly creates a new instance of RepositoryReadOnly. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewRepositoryReadOnly(t mockConstructorTestingTNewRepositoryReadOnly) *RepositoryReadOnly { - mock := &RepositoryReadOnly{} +func NewRepositoryReadOnly[K mdl.PossibleIdentifier, M db_repo.ModelBased[K]](t mockConstructorTestingTNewRepositoryReadOnly) *RepositoryReadOnly[K, M] { + mock := &RepositoryReadOnly[K, M]{} mock.Mock.Test(t) t.Cleanup(func() { mock.AssertExpectations(t) }) diff --git a/pkg/db-repo/mocks/TimeStampable.go b/pkg/db-repo/mocks/TimeStampable.go index 6d3aff4a6..0ef278df0 100644 --- a/pkg/db-repo/mocks/TimeStampable.go +++ b/pkg/db-repo/mocks/TimeStampable.go @@ -21,6 +21,92 @@ func (_m *TimeStampable) EXPECT() *TimeStampable_Expecter { return &TimeStampable_Expecter{mock: &_m.Mock} } +// GetCreatedAt provides a mock function with given fields: +func (_m *TimeStampable) GetCreatedAt() *time.Time { + ret := _m.Called() + + var r0 *time.Time + if rf, ok := ret.Get(0).(func() *time.Time); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*time.Time) + } + } + + return r0 +} + +// TimeStampable_GetCreatedAt_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetCreatedAt' +type TimeStampable_GetCreatedAt_Call struct { + *mock.Call +} + +// GetCreatedAt is a helper method to define mock.On call +func (_e *TimeStampable_Expecter) GetCreatedAt() *TimeStampable_GetCreatedAt_Call { + return &TimeStampable_GetCreatedAt_Call{Call: _e.mock.On("GetCreatedAt")} +} + +func (_c *TimeStampable_GetCreatedAt_Call) Run(run func()) *TimeStampable_GetCreatedAt_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *TimeStampable_GetCreatedAt_Call) Return(_a0 *time.Time) *TimeStampable_GetCreatedAt_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *TimeStampable_GetCreatedAt_Call) RunAndReturn(run func() *time.Time) *TimeStampable_GetCreatedAt_Call { + _c.Call.Return(run) + return _c +} + +// GetUpdatedAt provides a mock function with given fields: +func (_m *TimeStampable) GetUpdatedAt() *time.Time { + ret := _m.Called() + + var r0 *time.Time + if rf, ok := ret.Get(0).(func() *time.Time); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*time.Time) + } + } + + return r0 +} + +// TimeStampable_GetUpdatedAt_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetUpdatedAt' +type TimeStampable_GetUpdatedAt_Call struct { + *mock.Call +} + +// GetUpdatedAt is a helper method to define mock.On call +func (_e *TimeStampable_Expecter) GetUpdatedAt() *TimeStampable_GetUpdatedAt_Call { + return &TimeStampable_GetUpdatedAt_Call{Call: _e.mock.On("GetUpdatedAt")} +} + +func (_c *TimeStampable_GetUpdatedAt_Call) Run(run func()) *TimeStampable_GetUpdatedAt_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *TimeStampable_GetUpdatedAt_Call) Return(_a0 *time.Time) *TimeStampable_GetUpdatedAt_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *TimeStampable_GetUpdatedAt_Call) RunAndReturn(run func() *time.Time) *TimeStampable_GetUpdatedAt_Call { + _c.Call.Return(run) + return _c +} + // SetCreatedAt provides a mock function with given fields: createdAt func (_m *TimeStampable) SetCreatedAt(createdAt *time.Time) { _m.Called(createdAt) diff --git a/pkg/db-repo/model.go b/pkg/db-repo/model.go index 426cfc2bf..dc5744a82 100644 --- a/pkg/db-repo/model.go +++ b/pkg/db-repo/model.go @@ -9,8 +9,8 @@ import ( const ColumnUpdatedAt = "updated_at" //go:generate mockery --name ModelBased -type ModelBased interface { - mdl.Identifiable +type ModelBased[K mdl.PossibleIdentifier] interface { + mdl.Identifiable[K] TimeStampable } @@ -23,8 +23,19 @@ func (m *Model) GetId() *uint { return m.Id } +// TODO: better names are welcome +type DistributedModel struct { + Id *string `gorm:"primary_key"` + Timestamps +} + +func (m *DistributedModel) GetId() *string { + return m.Id +} + //go:generate mockery --name TimeStampable type TimeStampable interface { + TimestampAware SetUpdatedAt(updatedAt *time.Time) SetCreatedAt(createdAt *time.Time) } diff --git a/pkg/db-repo/notification.go b/pkg/db-repo/notification.go index 2652ea30f..1c6bf782d 100644 --- a/pkg/db-repo/notification.go +++ b/pkg/db-repo/notification.go @@ -20,9 +20,9 @@ type ( Publisher interface { Publish(ctx context.Context, typ string, version int, value interface{}, customAttributes ...map[string]string) error } - NotificationMap map[string][]Notifier - Notifier interface { - Send(ctx context.Context, notificationType string, value ModelBased) error + NotificationMap[K mdl.PossibleIdentifier] map[string][]Notifier[K] + Notifier[K mdl.PossibleIdentifier] interface { + Send(ctx context.Context, notificationType string, value ModelBased[K]) error } ) diff --git a/pkg/db-repo/notification_publisher.go b/pkg/db-repo/notification_publisher.go index 123c3f69c..e28852d3a 100644 --- a/pkg/db-repo/notification_publisher.go +++ b/pkg/db-repo/notification_publisher.go @@ -10,42 +10,44 @@ import ( "github.com/justtrackio/gosoline/pkg/mdl" ) -type publisherNotifier struct { +type publisherNotifier[K mdl.PossibleIdentifier] struct { notifier publisher Publisher transformer mdl.TransformerResolver } -func NewPublisherNotifier(_ context.Context, config cfg.Config, publisher Publisher, logger log.Logger, modelId mdl.ModelId, version int, transformer mdl.TransformerResolver) *publisherNotifier { +func NewPublisherNotifier[K mdl.PossibleIdentifier](config cfg.Config, publisher Publisher, logger log.Logger, modelId mdl.ModelId, version int, transformer mdl.TransformerResolver) Notifier[K] { modelId.PadFromConfig(config) notifier := newNotifier(logger, modelId, version) - return &publisherNotifier{ + return &publisherNotifier[K]{ notifier: notifier, publisher: publisher, transformer: transformer, } } -func (n *publisherNotifier) Send(ctx context.Context, notificationType string, value ModelBased) error { +func (n *publisherNotifier[K]) Send(ctx context.Context, notificationType string, value ModelBased[K]) error { logger := n.logger.WithContext(ctx) out := n.transformer("api", n.version, value) err := n.publisher.Publish(ctx, notificationType, n.version, out) if exec.IsRequestCanceled(err) { - logger.Info("request canceled while executing notification publish on %s for model %s with id %d", notificationType, n.modelId, value.GetId()) + logger.Info("request canceled while executing notification publish on %s for model %s with id %v", notificationType, n.modelId, value.GetId()) n.writeMetric(err) + return err } if err != nil { n.writeMetric(err) - return fmt.Errorf("error executing notification on %s for model %s with id %d: %w", notificationType, n.modelId, *value.GetId(), err) + + return fmt.Errorf("error executing notification on %s for model %s with id %v: %w", notificationType, n.modelId, *value.GetId(), err) } - logger.Info("published on %s successful, for model %s with id %d", notificationType, n.modelId, *value.GetId()) + logger.Info("published on %s successful, for model %s with id %v", notificationType, n.modelId, *value.GetId()) n.writeMetric(nil) return nil diff --git a/pkg/db-repo/notification_publisher_test.go b/pkg/db-repo/notification_publisher_test.go index d9fe14dec..729848d7c 100644 --- a/pkg/db-repo/notification_publisher_test.go +++ b/pkg/db-repo/notification_publisher_test.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/justtrackio/gosoline/pkg/cfg" - db_repo "github.com/justtrackio/gosoline/pkg/db-repo" + "github.com/justtrackio/gosoline/pkg/db-repo" logMocks "github.com/justtrackio/gosoline/pkg/log/mocks" "github.com/justtrackio/gosoline/pkg/mdl" mdlMocks "github.com/justtrackio/gosoline/pkg/mdlsub/mocks" @@ -26,7 +26,7 @@ func Test_Publish_Notifier(t *testing.T) { } transformer := func(view string, version int, in interface{}) (out interface{}) { - assert.Equal(t, mdl.Box(uint(3)), in.(db_repo.ModelBased).GetId()) + assert.Equal(t, mdl.Box(uint(3)), in.(db_repo.ModelBased[uint]).GetId()) assert.Equal(t, "api", view) assert.Equal(t, 1, version) @@ -45,7 +45,7 @@ func Test_Publish_Notifier(t *testing.T) { Environment: "test", } - notifier := db_repo.NewPublisherNotifier(context.Background(), cfg.New(), &publisher, logMocks.NewLoggerMockedAll(), modelId, 1, transformer) + notifier := db_repo.NewPublisherNotifier[uint](cfg.New(), &publisher, logMocks.NewLoggerMockedAll(), modelId, 1, transformer) err := notifier.Send(context.Background(), "CREATE", input) assert.NoError(t, err) diff --git a/pkg/db-repo/notification_repo.go b/pkg/db-repo/notification_repo.go index 95153a5c6..690cd7c39 100644 --- a/pkg/db-repo/notification_repo.go +++ b/pkg/db-repo/notification_repo.go @@ -6,38 +6,39 @@ import ( "github.com/hashicorp/go-multierror" "github.com/justtrackio/gosoline/pkg/log" + "github.com/justtrackio/gosoline/pkg/mdl" ) -type notifyingRepository struct { - Repository +type notifyingRepository[K mdl.PossibleIdentifier, M ModelBased[K]] struct { + Repository[K, M] logger log.Logger - notifiers NotificationMap + notifiers NotificationMap[K] } -func NewNotifyingRepository(logger log.Logger, base Repository) *notifyingRepository { - return ¬ifyingRepository{ +func NewNotifyingRepository[K mdl.PossibleIdentifier, M ModelBased[K]](logger log.Logger, base Repository[K, M]) Repository[K, M] { + return ¬ifyingRepository[K, M]{ Repository: base, logger: logger, - notifiers: make(NotificationMap), + notifiers: make(NotificationMap[K]), } } -func (r *notifyingRepository) AddNotifierAll(c Notifier) { +func (r *notifyingRepository[K, M]) AddNotifierAll(c Notifier[K]) { for _, t := range NotificationTypes { r.AddNotifier(t, c) } } -func (r *notifyingRepository) AddNotifier(t string, c Notifier) { +func (r *notifyingRepository[K, M]) AddNotifier(t string, c Notifier[K]) { if _, ok := r.notifiers[t]; !ok { - r.notifiers[t] = make([]Notifier, 0) + r.notifiers[t] = make([]Notifier[K], 0) } r.notifiers[t] = append(r.notifiers[t], c) } -func (r *notifyingRepository) Create(ctx context.Context, value ModelBased) error { +func (r *notifyingRepository[K, M]) Create(ctx context.Context, value M) error { if err := r.Repository.Create(ctx, value); err != nil { return err } @@ -45,7 +46,7 @@ func (r *notifyingRepository) Create(ctx context.Context, value ModelBased) erro return r.doCallback(ctx, Create, value) } -func (r *notifyingRepository) Update(ctx context.Context, value ModelBased) error { +func (r *notifyingRepository[K, M]) Update(ctx context.Context, value M) error { if err := r.Repository.Update(ctx, value); err != nil { return err } @@ -53,7 +54,7 @@ func (r *notifyingRepository) Update(ctx context.Context, value ModelBased) erro return r.doCallback(ctx, Update, value) } -func (r *notifyingRepository) Delete(ctx context.Context, value ModelBased) error { +func (r *notifyingRepository[K, M]) Delete(ctx context.Context, value M) error { if err := r.Repository.Delete(ctx, value); err != nil { return err } @@ -61,7 +62,7 @@ func (r *notifyingRepository) Delete(ctx context.Context, value ModelBased) erro return r.doCallback(ctx, Delete, value) } -func (r *notifyingRepository) doCallback(ctx context.Context, callbackType string, value ModelBased) error { +func (r *notifyingRepository[K, M]) doCallback(ctx context.Context, callbackType string, value M) error { if _, ok := r.notifiers[callbackType]; !ok { return nil } diff --git a/pkg/db-repo/repository.go b/pkg/db-repo/repository.go index a3b8deebd..31f91bd3f 100644 --- a/pkg/db-repo/repository.go +++ b/pkg/db-repo/repository.go @@ -4,9 +4,7 @@ import ( "context" "fmt" "reflect" - "strconv" "strings" - "time" "github.com/jinzhu/gorm" "github.com/justtrackio/gosoline/pkg/cfg" @@ -14,7 +12,6 @@ import ( "github.com/justtrackio/gosoline/pkg/db" "github.com/justtrackio/gosoline/pkg/log" "github.com/justtrackio/gosoline/pkg/mdl" - "github.com/justtrackio/gosoline/pkg/refl" "github.com/justtrackio/gosoline/pkg/tracing" ) @@ -41,10 +38,10 @@ type Settings struct { } //go:generate mockery --name RepositoryReadOnly -type RepositoryReadOnly interface { - Read(ctx context.Context, id *uint, out ModelBased) error - Query(ctx context.Context, qb *QueryBuilder, result interface{}) error - Count(ctx context.Context, qb *QueryBuilder, model ModelBased) (int, error) +type RepositoryReadOnly[K mdl.PossibleIdentifier, M ModelBased[K]] interface { + Read(ctx context.Context, id K) (M, error) + Query(ctx context.Context, qb *QueryBuilder) ([]M, error) + Count(ctx context.Context, qb *QueryBuilder) (int, error) GetModelId() string GetModelName() string @@ -52,22 +49,28 @@ type RepositoryReadOnly interface { } //go:generate mockery --name Repository -type Repository interface { - RepositoryReadOnly - Create(ctx context.Context, value ModelBased) error - Update(ctx context.Context, value ModelBased) error - Delete(ctx context.Context, value ModelBased) error +type Repository[K mdl.PossibleIdentifier, M ModelBased[K]] interface { + RepositoryReadOnly[K, M] + Create(ctx context.Context, value M) error + Update(ctx context.Context, value M) error + Delete(ctx context.Context, value M) error } -type repository struct { - logger log.Logger - tracer tracing.Tracer - orm *gorm.DB - clock clock.Clock - metadata Metadata +type ConfigurableRepository[K mdl.PossibleIdentifier, M ModelBased[K]] interface { + Repository[K, M] + SetModelSource(modelSource func() M) } -func New(config cfg.Config, logger log.Logger, s Settings) (*repository, error) { +type repository[K mdl.PossibleIdentifier, M ModelBased[K]] struct { + logger log.Logger + tracer tracing.Tracer + orm *gorm.DB + clock clock.Clock + metadata Metadata + modelSource func() M +} + +func New[K mdl.PossibleIdentifier, M ModelBased[K]](config cfg.Config, logger log.Logger, s Settings) (ConfigurableRepository[K, M], error) { tracer, err := tracing.ProvideTracer(config, logger) if err != nil { return nil, fmt.Errorf("can not create tracer: %w", err) @@ -81,13 +84,13 @@ func New(config cfg.Config, logger log.Logger, s Settings) (*repository, error) orm.Callback(). Update(). After("gorm:update_time_stamp"). - Register("gosoline:ignore_created_at_if_needed", ignoreCreatedAtIfNeeded) + Register("gosoline:ignore_created_at_if_needed", ignoreCreatedAtIfNeeded[K, M]) clk := clock.Provider - return NewWithInterfaces(logger, tracer, orm, clk, s.Metadata), nil + return NewWithInterfaces[K, M](logger, tracer, orm, clk, s.Metadata, CreateModel[M]), nil } -func NewWithDbSettings(config cfg.Config, logger log.Logger, dbSettings db.Settings, repoSettings Settings) (*repository, error) { +func NewWithDbSettings[K mdl.PossibleIdentifier, M ModelBased[K]](config cfg.Config, logger log.Logger, dbSettings db.Settings, repoSettings Settings) (ConfigurableRepository[K, M], error) { tracer, err := tracing.ProvideTracer(config, logger) if err != nil { return nil, fmt.Errorf("can not create tracer: %w", err) @@ -101,28 +104,33 @@ func NewWithDbSettings(config cfg.Config, logger log.Logger, dbSettings db.Setti orm.Callback(). Update(). After("gorm:update_time_stamp"). - Register("gosoline:ignore_created_at_if_needed", ignoreCreatedAtIfNeeded) + Register("gosoline:ignore_created_at_if_needed", ignoreCreatedAtIfNeeded[K, M]) clk := clock.Provider - return NewWithInterfaces(logger, tracer, orm, clk, repoSettings.Metadata), nil + return NewWithInterfaces[K, M](logger, tracer, orm, clk, repoSettings.Metadata, CreateModel[M]), nil } -func NewWithInterfaces(logger log.Logger, tracer tracing.Tracer, orm *gorm.DB, clock clock.Clock, metadata Metadata) *repository { - return &repository{ - logger: logger, - tracer: tracer, - orm: orm, - clock: clock, - metadata: metadata, +func NewWithInterfaces[K mdl.PossibleIdentifier, M ModelBased[K]](logger log.Logger, tracer tracing.Tracer, orm *gorm.DB, clock clock.Clock, metadata Metadata, modelSource func() M) ConfigurableRepository[K, M] { + return &repository[K, M]{ + logger: logger, + tracer: tracer, + orm: orm, + clock: clock, + metadata: metadata, + modelSource: modelSource, } } -func (r *repository) GetOrm() *gorm.DB { +func (r *repository[K, M]) GetOrm() *gorm.DB { return r.orm } -func (r *repository) Create(ctx context.Context, value ModelBased) error { +func (r *repository[K, M]) SetModelSource(modelSource func() M) { + r.modelSource = modelSource +} + +func (r *repository[K, M]) Create(ctx context.Context, value M) error { if !r.isQueryableModel(value) { return ErrCrossCreate } @@ -141,47 +149,57 @@ func (r *repository) Create(ctx context.Context, value ModelBased) error { if db.IsDuplicateEntryError(err) { logger.Warn("could not create model of type %s due to duplicate entry error: %s", modelId, err.Error()) + return &db.DuplicateEntryError{ Err: err, } } if err != nil { - logger.Error("could not create model of type %v: %w", modelId, err) - return err + return fmt.Errorf("could not create model of type %s: %w", modelId, err) } err = r.refreshAssociations(value, Create) if err != nil { - logger.Error("could not update associations of model type %v: %w", modelId, err) + return fmt.Errorf("could not update associations of model type %s: %w", modelId, err) + } + + logger.Info("created model of type %s with id %v", modelId, *value.GetId()) + + created, err := r.Read(ctx, *value.GetId()) + if err != nil { return err } - logger.Info("created model of type %s with id %d", modelId, *value.GetId()) + setValue(value, created) - return r.Read(ctx, value.GetId(), value) + return nil } -func (r *repository) Read(ctx context.Context, id *uint, out ModelBased) error { +func (r *repository[K, M]) Read(ctx context.Context, id K) (M, error) { + out := r.modelSource() + if !r.isQueryableModel(out) { - return ErrCrossRead + return out, ErrCrossRead } modelId := r.GetModelId() _, span := r.startSubSpan(ctx, "Get") defer span.Finish() - err := r.orm.First(out, *id).Error + err := r.orm.First(out, map[string]interface{}{ + r.metadata.PrimaryKeyWithoutTable(): id, + }).Error if gorm.IsRecordNotFoundError(err) { - return NewRecordNotFoundError(*id, modelId, err) + return out, NewRecordNotFoundError(idToString(id), modelId, err) } - return err + return out, err } -func (r *repository) Update(ctx context.Context, value ModelBased) error { +func (r *repository[K, M]) Update(ctx context.Context, value M) error { if !r.isQueryableModel(value) { return ErrCrossUpdate } @@ -198,30 +216,36 @@ func (r *repository) Update(ctx context.Context, value ModelBased) error { err := r.orm.Save(value).Error if db.IsDuplicateEntryError(err) { - logger.Warn("could not update model of type %s with id %d due to duplicate entry error: %s", modelId, mdl.EmptyIfNil(value.GetId()), err.Error()) + logger.Warn("could not update model of type %s with id %v due to duplicate entry error: %s", modelId, mdl.EmptyIfNil(value.GetId()), err.Error()) + return &db.DuplicateEntryError{ Err: err, } } if err != nil { - logger.Error("could not update model of type %s with id %d: %w", modelId, mdl.EmptyIfNil(value.GetId()), err) - return err + return fmt.Errorf("could not update model of type %s with id %v: %w", modelId, mdl.EmptyIfNil(value.GetId()), err) } err = r.refreshAssociations(value, Update) if err != nil { - logger.Error("could not update associations of model type %s with id %d: %w", modelId, *value.GetId(), err) + return fmt.Errorf("could not update associations of model type %s with id %v: %w", modelId, *value.GetId(), err) + } + + logger.Info("updated model of type %s with id %v", modelId, *value.GetId()) + + updated, err := r.Read(ctx, *value.GetId()) + if err != nil { return err } - logger.Info("updated model of type %s with id %d", modelId, *value.GetId()) + setValue(value, updated) - return r.Read(ctx, value.GetId(), value) + return nil } -func (r *repository) Delete(ctx context.Context, value ModelBased) error { +func (r *repository[K, M]) Delete(ctx context.Context, value M) error { if !r.isQueryableModel(value) { return ErrCrossDelete } @@ -234,96 +258,89 @@ func (r *repository) Delete(ctx context.Context, value ModelBased) error { err := r.refreshAssociations(value, Delete) if err != nil { - logger.Error("could not delete associations of model type %s with id %d: %w", modelId, *value.GetId(), err) - return err + return fmt.Errorf("could not delete associations of model type %s with id %v: %w", modelId, *value.GetId(), err) } err = r.orm.Delete(value).Error if err != nil { - logger.Error("could not delete model of type %s with id %d: %w", modelId, *value.GetId(), err) + return fmt.Errorf("could not delete model of type %s with id %v: %w", modelId, *value.GetId(), err) } - logger.Info("deleted model of type %s with id %d", modelId, *value.GetId()) + logger.Info("deleted model of type %s with id %v", modelId, *value.GetId()) - return err + return nil } -func (r *repository) isQueryableModel(model interface{}) bool { +func (r *repository[K, M]) isQueryableModel(model any) bool { tableName := r.orm.NewScope(model).TableName() return strings.EqualFold(tableName, r.GetMetadata().TableName) || tableName == "" } -func (r *repository) checkResultModel(result interface{}) error { - if refl.IsSlice(result) { - return fmt.Errorf("result slice has to be pointer to slice") - } - - if refl.IsPointerToSlice(result) { - model := reflect.ValueOf(result).Elem().Interface() +func (r *repository[K, M]) checkResultModel() error { + model := r.modelSource() - if !r.isQueryableModel(model) { - return fmt.Errorf("cross querying result slice has to be of same model") - } + if !r.isQueryableModel(model) { + return fmt.Errorf("cross querying result slice has to be of same model") } return nil } -func (r *repository) Query(ctx context.Context, qb *QueryBuilder, result interface{}) error { - err := r.checkResultModel(result) +func (r *repository[K, M]) Query(ctx context.Context, qb *QueryBuilder) ([]M, error) { + err := r.checkResultModel() if err != nil { - return err + return nil, err } _, span := r.startSubSpan(ctx, "Query") defer span.Finish() - db := r.orm.New() + query := r.orm.New() for _, j := range qb.joins { - db = db.Joins(j) + query = query.Joins(j) } - for i := range qb.where { - currentWhere := qb.where[i] + for i, currentWhere := range qb.where { if reflect.TypeOf(currentWhere).Kind() == reflect.Ptr || reflect.TypeOf(currentWhere).Kind() == reflect.Struct { if !r.isQueryableModel(currentWhere) { - return ErrCrossQuery + return nil, ErrCrossQuery } } - db = db.Where(currentWhere, qb.args[i]...) + query = query.Where(currentWhere, qb.args[i]...) } for _, g := range qb.groupBy { - db = db.Group(g) + query = query.Group(g) } for _, o := range qb.orderBy { - db = db.Order(fmt.Sprintf("%s %s", o.field, o.direction)) + query = query.Order(fmt.Sprintf("%s %s", o.field, o.direction)) } if qb.page != nil { - db = db.Offset(qb.page.offset) - db = db.Limit(qb.page.limit) + query = query.Offset(qb.page.offset) + query = query.Limit(qb.page.limit) } - db = db.Table(r.GetMetadata().TableName) + query = query.Table(r.GetMetadata().TableName) - err = db.Find(result).Error + result := make([]M, 0) + err = query.Find(&result).Error if gorm.IsRecordNotFoundError(err) { - return NewNoQueryResultsError(r.GetModelId(), err) + return nil, NewNoQueryResultsError(r.GetModelId(), err) } - return err + return result, err } -func (r *repository) Count(ctx context.Context, qb *QueryBuilder, model ModelBased) (int, error) { +func (r *repository[K, M]) Count(ctx context.Context, qb *QueryBuilder) (int, error) { _, span := r.startSubSpan(ctx, "Count") defer span.Finish() @@ -331,27 +348,61 @@ func (r *repository) Count(ctx context.Context, qb *QueryBuilder, model ModelBas Count int }{} - db := r.orm.New() + query := r.orm.New() for _, j := range qb.joins { - db = db.Joins(j) + query = query.Joins(j) } - for i := range qb.where { - db = db.Where(qb.where[i], qb.args[i]...) + for i, currentWhere := range qb.where { + if reflect.TypeOf(currentWhere).Kind() == reflect.Ptr || + reflect.TypeOf(currentWhere).Kind() == reflect.Struct { + + if !r.isQueryableModel(currentWhere) { + return 0, ErrCrossQuery + } + } + + query = query.Where(currentWhere, qb.args[i]...) } + model := r.modelSource() scope := r.orm.NewScope(model) tableName := scope.TableName() key := scope.PrimaryKey() sel := fmt.Sprintf("COUNT(DISTINCT %s.%s) AS count", tableName, key) - err := db.Table(tableName).Select(sel).Scan(&result).Error + err := query.Table(tableName).Select(sel).Scan(&result).Error return result.Count, err } -func (r *repository) refreshAssociations(model interface{}, op string) error { +func CreateModel[M any]() M { + var model M + value := reflect.ValueOf(model) + valueType := value.Type() + + switch value.Kind() { + case reflect.Pointer: + return reflect.New(valueType.Elem()).Interface().(M) + + case reflect.Map: + return reflect.MakeMap(valueType).Interface().(M) + + default: + return model + } +} + +func setValue[M any](value M, target M) { + reflected := reflect.ValueOf(value) + + if reflected.Kind() == reflect.Ptr { + reflected.Elem().Set(reflect.ValueOf(target).Elem()) + } +} + +func (r *repository[K, M]) refreshAssociations(model M, op string) error { typeReflection := reflect.TypeOf(model).Elem() valueReflection := reflect.ValueOf(model).Elem() @@ -386,16 +437,11 @@ func (r *repository) refreshAssociations(model interface{}, op string) error { scopeField, _ := scope.FieldByName(field.Name) switch op { - case Create: - fallthrough - - case Update: - switch scopeField.Relationship.Kind { - case "many_to_many": + case Create, Update: + if scopeField.Relationship.Kind == "many_to_many" { err = r.orm.Model(model).Association(scopeField.Name).Replace(values.Interface()).Error - - default: - assocIds := readIdsFromReflectValue(values) + } else { + assocIds := readIdsFromReflectValue[K](values) parentId := valueReflection.FieldByName("Id").Elem().Interface() tableName := scopeField.DBName @@ -413,8 +459,7 @@ func (r *repository) refreshAssociations(model interface{}, op string) error { } case Delete: - switch scopeField.Relationship.Kind { - case "has_many": + if scopeField.Relationship.Kind == "has_many" { id := valueReflection.FieldByName("Id").Elem().Interface() tableName := scopeField.DBName @@ -424,8 +469,7 @@ func (r *repository) refreshAssociations(model interface{}, op string) error { qry := fmt.Sprintf("DELETE FROM %s WHERE %s = %d", tableName, scopeField.Relationship.ForeignDBNames[0], id) err = r.orm.Exec(qry).Error - - default: + } else { err = r.orm.Model(model).Association(field.Name).Clear().Error } @@ -441,19 +485,19 @@ func (r *repository) refreshAssociations(model interface{}, op string) error { return nil } -func (r *repository) GetModelId() string { +func (r *repository[K, M]) GetModelId() string { return r.metadata.ModelId.String() } -func (r *repository) GetModelName() string { +func (r *repository[K, M]) GetModelName() string { return r.metadata.ModelId.Name } -func (r *repository) GetMetadata() Metadata { +func (r *repository[K, M]) GetMetadata() Metadata { return r.metadata } -func (r *repository) startSubSpan(ctx context.Context, action string) (context.Context, tracing.Span) { +func (r *repository[K, M]) startSubSpan(ctx context.Context, action string) (context.Context, tracing.Span) { modelName := r.GetModelId() spanName := fmt.Sprintf("db_repo.%v.%v", modelName, action) @@ -463,37 +507,25 @@ func (r *repository) startSubSpan(ctx context.Context, action string) (context.C return ctx, span } -func readIdsFromReflectValue(values reflect.Value) []string { +func readIdsFromReflectValue[K mdl.PossibleIdentifier](values reflect.Value) []string { ids := make([]string, 0) for j := 0; j < values.Len(); j++ { - id := values.Index(j).Elem().FieldByName("Id").Interface().(*uint) - ids = append(ids, strconv.Itoa(int(*id))) + id := values.Index(j).Elem().FieldByName("Id").Interface().(*K) + ids = append(ids, idToString(*id)) } return ids } -func ignoreCreatedAtIfNeeded(scope *gorm.Scope) { +func idToString[K mdl.PossibleIdentifier](id K) string { + return fmt.Sprintf("%v", id) +} + +func ignoreCreatedAtIfNeeded[K mdl.PossibleIdentifier, M ModelBased[K]](scope *gorm.Scope) { // if you perform an update and do not specify the CreatedAt field on your data, gorm will set it to time.Time{} // (0000-00-00 00:00:00 in mysql). To avoid this, we mark the field as ignored if it is empty - if m, ok := getModel(scope.Value); ok && (m.GetCreatedAt() == nil || *m.GetCreatedAt() == time.Time{}) { + if m, ok := scope.Value.(M); ok && mdl.IsNilOrEmpty(m.GetCreatedAt()) { scope.Search.Omit("CreatedAt") } } - -func getModel(value interface{}) (TimestampAware, bool) { - if value == nil { - return nil, false - } - - if m, ok := value.(TimestampAware); ok { - return m, true - } - - if val := reflect.ValueOf(value); val.Kind() == reflect.Ptr { - return getModel(val.Elem().Interface()) - } - - return nil, false -} diff --git a/pkg/db-repo/repository_test.go b/pkg/db-repo/repository_test.go index fd5b1d755..cc3e9bc2f 100644 --- a/pkg/db-repo/repository_test.go +++ b/pkg/db-repo/repository_test.go @@ -3,12 +3,14 @@ package db_repo_test import ( "context" "database/sql/driver" + "fmt" + "regexp" "testing" "time" goSqlMock "github.com/DATA-DOG/go-sqlmock" "github.com/justtrackio/gosoline/pkg/clock" - "github.com/justtrackio/gosoline/pkg/db-repo" + dbRepo "github.com/justtrackio/gosoline/pkg/db-repo" logMocks "github.com/justtrackio/gosoline/pkg/log/mocks" "github.com/justtrackio/gosoline/pkg/mdl" "github.com/justtrackio/gosoline/pkg/tracing" @@ -16,7 +18,7 @@ import ( ) type MyTestModel struct { - db_repo.Model + dbRepo.Model } const ( @@ -26,78 +28,78 @@ const ( hasMany = "hasMany" ) -var MyTestModelMetadata = db_repo.Metadata{ +var MyTestModelMetadata = dbRepo.Metadata{ ModelId: mdl.ModelId{ Application: "application", Name: "myTestModel", }, TableName: "my_test_models", PrimaryKey: "my_test_models.id", - Mappings: db_repo.FieldMappings{ - "myTestModel.id": db_repo.NewFieldMapping("my_test_models.id"), - "myTestModel.name": db_repo.NewFieldMapping("my_test_models.name"), + Mappings: dbRepo.FieldMappings{ + "myTestModel.id": dbRepo.NewFieldMapping("my_test_models.id"), + "myTestModel.name": dbRepo.NewFieldMapping("my_test_models.name"), }, } type ManyToMany struct { - db_repo.Model + dbRepo.Model RelModel []MyTestModel `gorm:"many2many:many_of_manies;" orm:"assoc_update"` } -var ManyToManyMetadata = db_repo.Metadata{ +var ManyToManyMetadata = dbRepo.Metadata{ ModelId: mdl.ModelId{ Application: "application", Name: "manyToMany", }, TableName: "many_to_manies", PrimaryKey: "many_to_manies.id", - Mappings: db_repo.FieldMappings{ - "manyToMany.id": db_repo.NewFieldMapping("many_to_manies.id"), + Mappings: dbRepo.FieldMappings{ + "manyToMany.id": dbRepo.NewFieldMapping("many_to_manies.id"), }, } type OneOfMany struct { - db_repo.Model + dbRepo.Model MyTestModel *MyTestModel `gorm:"foreignkey:MyTestModelId"` MyTestModelId *uint } -var OneOfManyMetadata = db_repo.Metadata{ +var OneOfManyMetadata = dbRepo.Metadata{ ModelId: mdl.ModelId{ Application: "application", Name: "oneOfMany", }, TableName: "one_of_manies", PrimaryKey: "one_of_manies.id", - Mappings: db_repo.FieldMappings{ - "oneOfMany.id": db_repo.NewFieldMapping("one_of_manies.id"), - "myTestModel.id": db_repo.NewFieldMapping("one_of_manies.my_test_model_id"), + Mappings: dbRepo.FieldMappings{ + "oneOfMany.id": dbRepo.NewFieldMapping("one_of_manies.id"), + "myTestModel.id": dbRepo.NewFieldMapping("one_of_manies.my_test_model_id"), }, } type HasMany struct { - db_repo.Model + dbRepo.Model Manies []*Ones `gorm:"association_autoupdate:true;association_autocreate:true;association_save_reference:true;" orm:"assoc_update"` } -var HasManyMetadata = db_repo.Metadata{ +var HasManyMetadata = dbRepo.Metadata{ ModelId: mdl.ModelId{ Application: "application", Name: "hasMany", }, TableName: "has_manies", PrimaryKey: "has_manies.id", - Mappings: db_repo.FieldMappings{ - "hasMany.id": db_repo.NewFieldMapping("has_manies.id"), + Mappings: dbRepo.FieldMappings{ + "hasMany.id": dbRepo.NewFieldMapping("has_manies.id"), }, } type Ones struct { - db_repo.Model + dbRepo.Model HasManyId *uint } -var metadatas = map[string]db_repo.Metadata{ +var metadatas = map[string]dbRepo.Metadata{ "myTestModel": MyTestModelMetadata, "manyToMany": ManyToManyMetadata, "oneOfMany": OneOfManyMetadata, @@ -118,21 +120,21 @@ var ( func TestRepository_Create(t *testing.T) { now := time.Unix(1549964818, 0) - dbc, repo := getTimedMocks(t, now, myTestModel) + dbc, repo := getTimedMocks[*MyTestModel](t, now, myTestModel, false) result := goSqlMock.NewResult(0, 1) dbc.ExpectBegin() - dbc.ExpectExec("INSERT INTO `my_test_models` \\(`id`,`updated_at`,`created_at`\\) VALUES \\(\\?,\\?,\\?\\)").WithArgs(id1, &now, &now).WillReturnResult(result) + dbc.ExpectExec("INSERT INTO `my_test_models` (`id`,`updated_at`,`created_at`) VALUES (?,?,?)").WithArgs(id1, &now, &now).WillReturnResult(result) dbc.ExpectCommit() model := MyTestModel{ - Model: db_repo.Model{ + Model: dbRepo.Model{ Id: id1, }, } rows := goSqlMock.NewRows([]string{"id", "updated_at", "created_at"}).AddRow(id1, &now, &now) - dbc.ExpectQuery("SELECT \\* FROM `my_test_models` WHERE `my_test_models`\\.`id` = \\? AND \\(\\(`my_test_models`\\.`id` = 1\\)\\) ORDER BY `my_test_models`\\.`id` ASC LIMIT 1").WillReturnRows(rows) + dbc.ExpectQuery("SELECT * FROM `my_test_models` WHERE (`my_test_models`.`id` = ?) ORDER BY `my_test_models`.`id` ASC LIMIT 1").WithArgs(1).WillReturnRows(rows) err := repo.Create(context.Background(), &model) @@ -147,24 +149,24 @@ func TestRepository_Create(t *testing.T) { func TestRepository_CreateManyToManyNoRelation(t *testing.T) { now := time.Unix(1549964818, 0) - dbc, repo := getTimedMocks(t, now, manyToMany) + dbc, repo := getTimedMocks[*ManyToMany](t, now, manyToMany, false) result := goSqlMock.NewResult(0, 1) delRes := goSqlMock.NewResult(0, 0) dbc.ExpectBegin() - dbc.ExpectExec("INSERT INTO `many_to_manies` \\(`id`,`updated_at`,`created_at`\\) VALUES \\(\\?,\\?,\\?\\)").WithArgs(id1, &now, &now).WillReturnResult(result) + dbc.ExpectExec("INSERT INTO `many_to_manies` (`id`,`updated_at`,`created_at`) VALUES (?,?,?)").WithArgs(id1, &now, &now).WillReturnResult(result) dbc.ExpectCommit() dbc.ExpectBegin() - dbc.ExpectExec("DELETE FROM `many_of_manies` WHERE \\(`many_to_many_id` IN \\(\\?\\)\\)").WithArgs(id1).WillReturnResult(delRes) + dbc.ExpectExec("DELETE FROM `many_of_manies` WHERE (`many_to_many_id` IN (?))").WithArgs(id1).WillReturnResult(delRes) dbc.ExpectCommit() rows := goSqlMock.NewRows([]string{"id", "updated_at", "created_at"}).AddRow(id1, &now, &now) - dbc.ExpectQuery("SELECT \\* FROM `many_to_manies` WHERE `many_to_manies`\\.`id` = \\? AND \\(\\(`many_to_manies`\\.`id` = 1\\)\\) ORDER BY `many_to_manies`\\.`id` ASC LIMIT 1").WillReturnRows(rows) - dbc.ExpectQuery("SELECT \\* FROM `my_test_models` INNER JOIN `many_of_manies` ON `many_of_manies`\\.`my_test_model_id` = `my_test_models`\\.`id` WHERE \\(`many_of_manies`\\.`many_to_many_id` IN \\(\\?\\)\\)").WillReturnRows(rows) + dbc.ExpectQuery("SELECT * FROM `many_to_manies` WHERE (`many_to_manies`.`id` = ?) ORDER BY `many_to_manies`.`id` ASC LIMIT 1").WithArgs(1).WillReturnRows(rows) + dbc.ExpectQuery("SELECT * FROM `my_test_models` INNER JOIN `many_of_manies` ON `many_of_manies`.`my_test_model_id` = `my_test_models`.`id` WHERE (`many_of_manies`.`many_to_many_id` IN (?))").WillReturnRows(rows) model := ManyToMany{ - Model: db_repo.Model{ + Model: dbRepo.Model{ Id: id1, }, } @@ -182,7 +184,7 @@ func TestRepository_CreateManyToManyNoRelation(t *testing.T) { func TestRepository_CreateManyToMany(t *testing.T) { now := time.Unix(1549964818, 0) - dbc, repo := getTimedMocks(t, now, manyToMany) + dbc, repo := getTimedMocks[*ManyToMany](t, now, manyToMany, true) result := goSqlMock.NewResult(0, 1) delRes := goSqlMock.NewResult(0, 0) @@ -200,16 +202,16 @@ func TestRepository_CreateManyToMany(t *testing.T) { dbc.ExpectCommit() rows := goSqlMock.NewRows([]string{"id", "updated_at", "created_at"}).AddRow(id1, &now, &now) - dbc.ExpectQuery("SELECT \\* FROM `many_to_manies` WHERE `many_to_manies`\\.`id` = \\? AND \\(\\(`many_to_manies`\\.`id` = 1\\)\\) ORDER BY `many_to_manies`\\.`id` ASC LIMIT 1").WillReturnRows(rows) + dbc.ExpectQuery("SELECT \\* FROM `many_to_manies` WHERE \\(`many_to_manies`\\.`id` = \\?\\) ORDER BY `many_to_manies`\\.`id` ASC LIMIT 1").WithArgs(1).WillReturnRows(rows) dbc.ExpectQuery("SELECT \\* FROM `my_test_models` INNER JOIN `many_of_manies` ON `many_of_manies`.`my_test_model_id` = `my_test_models`\\.`id` WHERE \\(`many_of_manies`.`many_to_many_id` IN \\(\\?\\)\\)").WillReturnRows(rows) model := ManyToMany{ - Model: db_repo.Model{ + Model: dbRepo.Model{ Id: id1, }, RelModel: []MyTestModel{ { - Model: db_repo.Model{ + Model: dbRepo.Model{ Id: id42, }, }, @@ -229,21 +231,21 @@ func TestRepository_CreateManyToMany(t *testing.T) { func TestRepository_CreateManyToOneNoRelation(t *testing.T) { now := time.Unix(1549964818, 0) - dbc, repo := getTimedMocks(t, now, oneOfMany) + dbc, repo := getTimedMocks[*OneOfMany](t, now, oneOfMany, false) result := goSqlMock.NewResult(0, 1) dbc.ExpectBegin() - dbc.ExpectExec("INSERT INTO `one_of_manies` \\(`id`,`updated_at`,`created_at`,`my_test_model_id`\\) VALUES \\(\\?,\\?,\\?,\\?\\)").WithArgs(id1, &now, &now, (*uint)(nil)).WillReturnResult(result) + dbc.ExpectExec("INSERT INTO `one_of_manies` (`id`,`updated_at`,`created_at`,`my_test_model_id`) VALUES (?,?,?,?)").WithArgs(id1, &now, &now, (*uint)(nil)).WillReturnResult(result) dbc.ExpectCommit() model := OneOfMany{ - Model: db_repo.Model{ + Model: dbRepo.Model{ Id: id1, }, } rows := goSqlMock.NewRows([]string{"id", "updated_at", "created_at", "my_test_model_id"}).AddRow(id1, &now, &now, (*uint)(nil)) - dbc.ExpectQuery("SELECT \\* FROM `one_of_manies` WHERE `one_of_manies`\\.`id` = \\? AND \\(\\(`one_of_manies`\\.`id` = 1\\)\\) ORDER BY `one_of_manies`\\.`id` ASC LIMIT 1").WillReturnRows(rows) + dbc.ExpectQuery("SELECT * FROM `one_of_manies` WHERE (`one_of_manies`.`id` = ?) ORDER BY `one_of_manies`.`id` ASC LIMIT 1").WithArgs(1).WillReturnRows(rows) err := repo.Create(context.Background(), &model) @@ -258,24 +260,24 @@ func TestRepository_CreateManyToOneNoRelation(t *testing.T) { func TestRepository_CreateManyToOne(t *testing.T) { now := time.Unix(1549964818, 0) - dbc, repo := getTimedMocks(t, now, oneOfMany) + dbc, repo := getTimedMocks[*OneOfMany](t, now, oneOfMany, false) result := goSqlMock.NewResult(0, 1) dbc.ExpectBegin() - dbc.ExpectExec("INSERT INTO `one_of_manies` \\(`id`,`updated_at`,`created_at`,`my_test_model_id`\\) VALUES \\(\\?,\\?,\\?,\\?\\)").WithArgs(id1, &now, &now, id42).WillReturnResult(result) + dbc.ExpectExec("INSERT INTO `one_of_manies` (`id`,`updated_at`,`created_at`,`my_test_model_id`) VALUES (?,?,?,?)").WithArgs(id1, &now, &now, id42).WillReturnResult(result) dbc.ExpectCommit() rows := goSqlMock.NewRows([]string{"id", "updated_at", "created_at", "my_test_model_id"}).AddRow(id1, &now, &now, id42) - dbc.ExpectQuery("SELECT \\* FROM `one_of_manies` WHERE `one_of_manies`\\.`id` = \\? AND \\(\\(`one_of_manies`\\.`id` = 1\\)\\) ORDER BY `one_of_manies`\\.`id` ASC LIMIT 1").WillReturnRows(rows) - dbc.ExpectQuery("SELECT \\* FROM `my_test_models` WHERE \\(`id` IN \\(\\?\\)\\) ORDER BY `my_test_models`\\.`id` ASC").WithArgs(id42).WillReturnRows(rows) + dbc.ExpectQuery("SELECT * FROM `one_of_manies` WHERE (`one_of_manies`.`id` = ?) ORDER BY `one_of_manies`.`id` ASC LIMIT 1").WithArgs(1).WillReturnRows(rows) + dbc.ExpectQuery("SELECT * FROM `my_test_models` WHERE (`id` IN (?)) ORDER BY `my_test_models`.`id` ASC").WithArgs(id42).WillReturnRows(rows) model := OneOfMany{ - Model: db_repo.Model{ + Model: dbRepo.Model{ Id: id1, }, MyTestModel: &MyTestModel{ - Model: db_repo.Model{ + Model: dbRepo.Model{ Id: id42, }, }, @@ -295,21 +297,21 @@ func TestRepository_CreateManyToOne(t *testing.T) { func TestRepository_CreateHasManyNoRelation(t *testing.T) { now := time.Unix(1549964818, 0) - dbc, repo := getTimedMocks(t, now, hasMany) + dbc, repo := getTimedMocks[*HasMany](t, now, hasMany, false) result := goSqlMock.NewResult(0, 1) delResult := goSqlMock.NewResult(0, 0) dbc.ExpectBegin() - dbc.ExpectExec("INSERT INTO `has_manies` \\(`id`,`updated_at`,`created_at`\\) VALUES \\(\\?,\\?,\\?\\)").WithArgs(id1, &now, &now).WillReturnResult(result) + dbc.ExpectExec("INSERT INTO `has_manies` (`id`,`updated_at`,`created_at`) VALUES (?,?,?)").WithArgs(id1, &now, &now).WillReturnResult(result) dbc.ExpectCommit() dbc.ExpectExec("DELETE FROM manies WHERE has_many_id = 1").WillReturnResult(delResult) rows := goSqlMock.NewRows([]string{"id", "updated_at", "created_at"}).AddRow(id1, &now, &now) - dbc.ExpectQuery("SELECT \\* FROM `has_manies` WHERE `has_manies`\\.`id` = \\? AND \\(\\(`has_manies`\\.`id` = 1\\)\\) ORDER BY `has_manies`\\.`id` ASC LIMIT 1").WillReturnRows(rows) - dbc.ExpectQuery("SELECT \\* FROM `ones` WHERE \\(`has_many_id` IN \\(\\?\\)\\) ORDER BY `ones`\\.`id` ASC").WillReturnRows(rows) + dbc.ExpectQuery("SELECT * FROM `has_manies` WHERE (`has_manies`.`id` = ?) ORDER BY `has_manies`.`id` ASC LIMIT 1").WithArgs(1).WillReturnRows(rows) + dbc.ExpectQuery("SELECT * FROM `ones` WHERE (`has_many_id` IN (?)) ORDER BY `ones`.`id` ASC").WillReturnRows(rows) model := HasMany{ - Model: db_repo.Model{ + Model: dbRepo.Model{ Id: id1, }, Manies: []*Ones{}, @@ -328,24 +330,24 @@ func TestRepository_CreateHasManyNoRelation(t *testing.T) { func TestRepository_CreateHasMany(t *testing.T) { now := time.Unix(1549964818, 0) - dbc, repo := getTimedMocks(t, now, hasMany) + dbc, repo := getTimedMocks[*HasMany](t, now, hasMany, false) result := goSqlMock.NewResult(0, 1) delResult := goSqlMock.NewResult(0, 0) dbc.ExpectBegin() - dbc.ExpectExec("INSERT INTO `has_manies` \\(`updated_at`,`created_at`\\) VALUES \\(\\?,\\?\\)").WithArgs(&now, &now).WillReturnResult(result) - dbc.ExpectExec("INSERT INTO `ones` \\(`updated_at`,`created_at`,`has_many_id`\\) VALUES \\(\\?,\\?,\\?\\)").WithArgs(goSqlMock.AnyArg(), goSqlMock.AnyArg(), 0).WillReturnResult(result) - dbc.ExpectExec("INSERT INTO `ones` \\(`updated_at`,`created_at`,`has_many_id`\\) VALUES \\(\\?,\\?,\\?\\)").WithArgs(goSqlMock.AnyArg(), goSqlMock.AnyArg(), 0).WillReturnResult(result) + dbc.ExpectExec("INSERT INTO `has_manies` (`updated_at`,`created_at`) VALUES (?,?)").WithArgs(&now, &now).WillReturnResult(result) + dbc.ExpectExec("INSERT INTO `ones` (`updated_at`,`created_at`,`has_many_id`) VALUES (?,?,?)").WithArgs(goSqlMock.AnyArg(), goSqlMock.AnyArg(), 0).WillReturnResult(result) + dbc.ExpectExec("INSERT INTO `ones` (`updated_at`,`created_at`,`has_many_id`) VALUES (?,?,?)").WithArgs(goSqlMock.AnyArg(), goSqlMock.AnyArg(), 0).WillReturnResult(result) dbc.ExpectCommit() - dbc.ExpectExec("DELETE FROM manies WHERE has_many_id = 0 AND id NOT IN \\(0,0\\)").WillReturnResult(delResult) + dbc.ExpectExec("DELETE FROM manies WHERE has_many_id = 0 AND id NOT IN (0,0)").WillReturnResult(delResult) rows := goSqlMock.NewRows([]string{"id", "updated_at", "created_at"}).AddRow(id1, &now, &now) - dbc.ExpectQuery("SELECT \\* FROM `has_manies` WHERE `has_manies`\\.`id` = \\? AND \\(\\(`has_manies`\\.`id` = 0\\)\\) ORDER BY `has_manies`\\.`id` ASC LIMIT 1").WillReturnRows(rows) - dbc.ExpectQuery("SELECT \\* FROM `ones` WHERE \\(`has_many_id` IN \\(\\?\\)\\) ORDER BY `ones`\\.`id` ASC").WillReturnRows(rows) + dbc.ExpectQuery("SELECT * FROM `has_manies` WHERE (`has_manies`.`id` = ?) ORDER BY `has_manies`.`id` ASC LIMIT 1").WithArgs(0).WillReturnRows(rows) + dbc.ExpectQuery("SELECT * FROM `ones` WHERE (`has_many_id` IN (?)) ORDER BY `ones`.`id` ASC").WillReturnRows(rows) model := HasMany{ - Model: db_repo.Model{}, + Model: dbRepo.Model{}, Manies: []*Ones{ {}, {}, @@ -364,20 +366,20 @@ func TestRepository_CreateHasMany(t *testing.T) { } func TestRepository_Update(t *testing.T) { - dbc, repo := getMocks(t, myTestModel) + dbc, repo := getMocks[*MyTestModel](t, myTestModel, false) now := time.Unix(1549964818, 0) result := goSqlMock.NewResult(0, 1) dbc.ExpectBegin() - dbc.ExpectExec("UPDATE `my_test_models` SET `updated_at` = \\? WHERE `my_test_models`\\.`id` = \\?").WithArgs(goSqlMock.AnyArg(), id1).WillReturnResult(result) + dbc.ExpectExec("UPDATE `my_test_models` SET `updated_at` = ? WHERE `my_test_models`.`id` = ?").WithArgs(goSqlMock.AnyArg(), id1).WillReturnResult(result) dbc.ExpectCommit() rows := goSqlMock.NewRows([]string{"id", "updated_at", "created_at"}).AddRow(id1, &now, &now) - dbc.ExpectQuery("SELECT \\* FROM `my_test_models` WHERE `my_test_models`\\.`id` = \\? AND \\(\\(`my_test_models`\\.`id` = 1\\)\\) ORDER BY `my_test_models`\\.`id` ASC LIMIT 1").WillReturnRows(rows) + dbc.ExpectQuery("SELECT * FROM `my_test_models` WHERE (`my_test_models`.`id` = ?) ORDER BY `my_test_models`.`id` ASC LIMIT 1").WithArgs(1).WillReturnRows(rows) model := MyTestModel{ - Model: db_repo.Model{ + Model: dbRepo.Model{ Id: id1, }, } @@ -392,23 +394,23 @@ func TestRepository_Update(t *testing.T) { } func TestRepository_UpdateManyToManyNoRelation(t *testing.T) { - dbc, repo := getMocks(t, manyToMany) + dbc, repo := getMocks[*ManyToMany](t, manyToMany, false) now := time.Unix(1549964818, 0) result := goSqlMock.NewResult(0, 1) dbc.ExpectBegin() - dbc.ExpectExec("UPDATE `many_to_manies` SET `updated_at` = \\? WHERE `many_to_manies`\\.`id` = \\?").WithArgs(goSqlMock.AnyArg(), id1).WillReturnResult(result) + dbc.ExpectExec("UPDATE `many_to_manies` SET `updated_at` = ? WHERE `many_to_manies`.`id` = ?").WithArgs(goSqlMock.AnyArg(), id1).WillReturnResult(result) dbc.ExpectCommit() dbc.ExpectBegin() - dbc.ExpectExec("DELETE FROM `many_of_manies` WHERE \\(`many_to_many_id` IN \\(\\?\\)\\)").WithArgs(id1).WillReturnResult(result) + dbc.ExpectExec("DELETE FROM `many_of_manies` WHERE (`many_to_many_id` IN (?))").WithArgs(id1).WillReturnResult(result) dbc.ExpectCommit() rows := goSqlMock.NewRows([]string{"id", "updated_at", "created_at"}).AddRow(id1, &now, &now) - dbc.ExpectQuery("SELECT \\* FROM `many_to_manies` WHERE `many_to_manies`\\.`id` = \\? AND \\(\\(`many_to_manies`\\.`id` = 1\\)\\) ORDER BY `many_to_manies`\\.`id` ASC LIMIT 1").WithArgs(id1).WillReturnRows(rows) - dbc.ExpectQuery("SELECT \\* FROM `my_test_models` INNER JOIN `many_of_manies` ON `many_of_manies`.`my_test_model_id` = `my_test_models`\\.`id` WHERE \\(`many_of_manies`.`many_to_many_id` IN \\(\\?\\)\\)").WithArgs(id1).WillReturnRows(rows) + dbc.ExpectQuery("SELECT * FROM `many_to_manies` WHERE (`many_to_manies`.`id` = ?) ORDER BY `many_to_manies`.`id` ASC LIMIT 1").WithArgs(id1).WillReturnRows(rows) + dbc.ExpectQuery("SELECT * FROM `my_test_models` INNER JOIN `many_of_manies` ON `many_of_manies`.`my_test_model_id` = `my_test_models`.`id` WHERE (`many_of_manies`.`many_to_many_id` IN (?))").WithArgs(id1).WillReturnRows(rows) model := ManyToMany{ - Model: db_repo.Model{ + Model: dbRepo.Model{ Id: id1, }, } @@ -423,7 +425,7 @@ func TestRepository_UpdateManyToManyNoRelation(t *testing.T) { } func TestRepository_UpdateManyToMany(t *testing.T) { - dbc, repo := getMocks(t, manyToMany) + dbc, repo := getMocks[*ManyToMany](t, manyToMany, true) now := time.Unix(1549964818, 0) result := goSqlMock.NewResult(0, 1) @@ -440,16 +442,16 @@ func TestRepository_UpdateManyToMany(t *testing.T) { dbc.ExpectCommit() rows := goSqlMock.NewRows([]string{"id", "updated_at", "created_at"}).AddRow(id1, &now, &now) - dbc.ExpectQuery("SELECT \\* FROM `many_to_manies` WHERE `many_to_manies`\\.`id` = \\? AND \\(\\(`many_to_manies`\\.`id` = 1\\)\\) ORDER BY `many_to_manies`\\.`id` ASC LIMIT 1").WillReturnRows(rows) + dbc.ExpectQuery("SELECT \\* FROM `many_to_manies` WHERE \\(`many_to_manies`\\.`id` = \\?\\) ORDER BY `many_to_manies`\\.`id` ASC LIMIT 1").WithArgs(1).WillReturnRows(rows) dbc.ExpectQuery("SELECT \\* FROM `my_test_models` INNER JOIN `many_of_manies` ON `many_of_manies`.`my_test_model_id` = `my_test_models`\\.`id` WHERE \\(`many_of_manies`.`many_to_many_id` IN \\(\\?\\)\\)").WillReturnRows(rows) model := ManyToMany{ - Model: db_repo.Model{ + Model: dbRepo.Model{ Id: id1, }, RelModel: []MyTestModel{ { - Model: db_repo.Model{ + Model: dbRepo.Model{ Id: id42, }, }, @@ -466,19 +468,19 @@ func TestRepository_UpdateManyToMany(t *testing.T) { } func TestRepository_UpdateManyToOneNoRelation(t *testing.T) { - dbc, repo := getMocks(t, oneOfMany) + dbc, repo := getMocks[*OneOfMany](t, oneOfMany, false) now := time.Unix(1549964818, 0) result := goSqlMock.NewResult(0, 1) dbc.ExpectBegin() - dbc.ExpectExec("UPDATE `one_of_manies` SET `updated_at` = \\?, `my_test_model_id` = \\? WHERE `one_of_manies`\\.`id` = \\?").WithArgs(goSqlMock.AnyArg(), (*uint)(nil), id1).WillReturnResult(result) + dbc.ExpectExec("UPDATE `one_of_manies` SET `updated_at` = ?, `my_test_model_id` = ? WHERE `one_of_manies`.`id` = ?").WithArgs(goSqlMock.AnyArg(), (*uint)(nil), id1).WillReturnResult(result) dbc.ExpectCommit() rows := goSqlMock.NewRows([]string{"id", "updated_at", "created_at"}).AddRow(id1, &now, &now) - dbc.ExpectQuery("SELECT \\* FROM `one_of_manies` WHERE `one_of_manies`\\.`id` = \\? AND \\(\\(`one_of_manies`\\.`id` = 1\\)\\) ORDER BY `one_of_manies`\\.`id` ASC LIMIT 1").WithArgs(id1).WillReturnRows(rows) + dbc.ExpectQuery("SELECT * FROM `one_of_manies` WHERE (`one_of_manies`.`id` = ?) ORDER BY `one_of_manies`.`id` ASC LIMIT 1").WithArgs(id1).WillReturnRows(rows) model := OneOfMany{ - Model: db_repo.Model{ + Model: dbRepo.Model{ Id: id1, }, MyTestModel: nil, @@ -495,24 +497,25 @@ func TestRepository_UpdateManyToOneNoRelation(t *testing.T) { } func TestRepository_UpdateManyToOne(t *testing.T) { - dbc, repo := getMocks(t, oneOfMany) + dbc, repo := getMocks[*OneOfMany](t, oneOfMany, false) now := time.Unix(1549964818, 0) result := goSqlMock.NewResult(0, 1) dbc.ExpectBegin() - dbc.ExpectExec("UPDATE `one_of_manies` SET `updated_at` = \\?, `my_test_model_id` = \\? WHERE `one_of_manies`\\.`id` = \\?").WithArgs(goSqlMock.AnyArg(), goSqlMock.AnyArg(), id1).WillReturnResult(result) + dbc.ExpectExec("UPDATE `one_of_manies` SET `updated_at` = ?, `my_test_model_id` = ? WHERE `one_of_manies`.`id` = ?").WithArgs(goSqlMock.AnyArg(), goSqlMock.AnyArg(), id1).WillReturnResult(result) dbc.ExpectCommit() - rows := goSqlMock.NewRows([]string{"id", "updated_at", "created_at"}).AddRow(id1, &now, &now) - dbc.ExpectQuery("SELECT \\* FROM `one_of_manies` WHERE `one_of_manies`\\.`id` = \\? AND \\(\\(`one_of_manies`\\.`id` = 1\\)\\) ORDER BY `one_of_manies`\\.`id` ASC LIMIT 1").WithArgs(id1).WillReturnRows(rows) - dbc.ExpectQuery("SELECT \\* FROM `my_test_models` WHERE \\(`id` IN \\(\\?\\)\\) ORDER BY `my_test_models`\\.`id` ASC").WithArgs(id42).WillReturnRows(rows) + oneOfManyRows := goSqlMock.NewRows([]string{"id", "updated_at", "created_at", "my_test_model_id"}).AddRow(id1, &now, &now, id42) + myTestModelRows := goSqlMock.NewRows([]string{"id", "updated_at", "created_at"}).AddRow(id42, &now, &now) + dbc.ExpectQuery("SELECT * FROM `one_of_manies` WHERE (`one_of_manies`.`id` = ?) ORDER BY `one_of_manies`.`id` ASC LIMIT 1").WithArgs(id1).WillReturnRows(oneOfManyRows) + dbc.ExpectQuery("SELECT * FROM `my_test_models` WHERE (`id` IN (?)) ORDER BY `my_test_models`.`id` ASC").WithArgs(id42).WillReturnRows(myTestModelRows) model := OneOfMany{ - Model: db_repo.Model{ + Model: dbRepo.Model{ Id: id1, }, MyTestModel: &MyTestModel{ - Model: db_repo.Model{ + Model: dbRepo.Model{ Id: id42, }, }, @@ -529,25 +532,25 @@ func TestRepository_UpdateManyToOne(t *testing.T) { } func TestRepository_UpdateHasMany(t *testing.T) { - dbc, repo := getMocks(t, hasMany) + dbc, repo := getMocks[*HasMany](t, hasMany, false) now := time.Unix(1549964818, 0) result := goSqlMock.NewResult(0, 1) delResult := goSqlMock.NewResult(0, 0) dbc.ExpectBegin() - dbc.ExpectExec("UPDATE `has_manies` SET `updated_at` = \\? WHERE `has_manies`\\.`id` = \\?").WithArgs(goSqlMock.AnyArg(), id1).WillReturnResult(result) - dbc.ExpectExec("INSERT INTO `ones` \\(`updated_at`,`created_at`,`has_many_id`\\) VALUES \\(\\?,\\?,\\?\\)").WithArgs(goSqlMock.AnyArg(), goSqlMock.AnyArg(), *id1).WillReturnResult(result) - dbc.ExpectExec("INSERT INTO `ones` \\(`updated_at`,`created_at`,`has_many_id`\\) VALUES \\(\\?,\\?,\\?\\)").WithArgs(goSqlMock.AnyArg(), goSqlMock.AnyArg(), *id1).WillReturnResult(result) - dbc.ExpectExec("INSERT INTO `ones` \\(`updated_at`,`created_at`,`has_many_id`\\) VALUES \\(\\?,\\?,\\?\\)").WithArgs(goSqlMock.AnyArg(), goSqlMock.AnyArg(), *id1).WillReturnResult(result) + dbc.ExpectExec("UPDATE `has_manies` SET `updated_at` = ? WHERE `has_manies`.`id` = ?").WithArgs(goSqlMock.AnyArg(), id1).WillReturnResult(result) + dbc.ExpectExec("INSERT INTO `ones` (`updated_at`,`created_at`,`has_many_id`) VALUES (?,?,?)").WithArgs(goSqlMock.AnyArg(), goSqlMock.AnyArg(), *id1).WillReturnResult(result) + dbc.ExpectExec("INSERT INTO `ones` (`updated_at`,`created_at`,`has_many_id`) VALUES (?,?,?)").WithArgs(goSqlMock.AnyArg(), goSqlMock.AnyArg(), *id1).WillReturnResult(result) + dbc.ExpectExec("INSERT INTO `ones` (`updated_at`,`created_at`,`has_many_id`) VALUES (?,?,?)").WithArgs(goSqlMock.AnyArg(), goSqlMock.AnyArg(), *id1).WillReturnResult(result) dbc.ExpectCommit() - dbc.ExpectExec("DELETE FROM manies WHERE has_many_id = 1 AND id NOT IN \\(0,0,0\\)").WillReturnResult(delResult) + dbc.ExpectExec("DELETE FROM manies WHERE has_many_id = 1 AND id NOT IN (0,0,0)").WillReturnResult(delResult) rows := goSqlMock.NewRows([]string{"id", "updated_at", "created_at"}).AddRow(id1, &now, &now) - dbc.ExpectQuery("SELECT \\* FROM `has_manies` WHERE `has_manies`\\.`id` = \\? AND \\(\\(`has_manies`\\.`id` = 1\\)\\) ORDER BY `has_manies`\\.`id` ASC LIMIT 1").WithArgs(id1).WillReturnRows(rows) - dbc.ExpectQuery("SELECT \\* FROM `ones` WHERE \\(`has_many_id` IN \\(\\?\\)\\) ORDER BY `ones`\\.`id` ASC").WithArgs(id1).WillReturnRows(rows) + dbc.ExpectQuery("SELECT * FROM `has_manies` WHERE (`has_manies`.`id` = ?) ORDER BY `has_manies`.`id` ASC LIMIT 1").WithArgs(id1).WillReturnRows(rows) + dbc.ExpectQuery("SELECT * FROM `ones` WHERE (`has_many_id` IN (?)) ORDER BY `ones`.`id` ASC").WithArgs(id1).WillReturnRows(rows) model := HasMany{ - Model: db_repo.Model{ + Model: dbRepo.Model{ Id: id1, }, Manies: []*Ones{ @@ -565,23 +568,23 @@ func TestRepository_UpdateHasMany(t *testing.T) { } func TestRepository_UpdateHasManyNoRelation(t *testing.T) { - dbc, repo := getMocks(t, hasMany) + dbc, repo := getMocks[*HasMany](t, hasMany, false) now := time.Unix(1549964818, 0) result := goSqlMock.NewResult(0, 1) delResult := goSqlMock.NewResult(0, 0) dbc.ExpectBegin() - dbc.ExpectExec("UPDATE `has_manies` SET `updated_at` = \\? WHERE `has_manies`\\.`id` = \\?").WithArgs(goSqlMock.AnyArg(), id1).WillReturnResult(result) + dbc.ExpectExec("UPDATE `has_manies` SET `updated_at` = ? WHERE `has_manies`.`id` = ?").WithArgs(goSqlMock.AnyArg(), id1).WillReturnResult(result) dbc.ExpectCommit() dbc.ExpectExec("DELETE FROM manies WHERE has_many_id = 1").WillReturnResult(delResult) rows := goSqlMock.NewRows([]string{"id", "updated_at", "created_at"}).AddRow(id1, &now, &now) - dbc.ExpectQuery("SELECT \\* FROM `has_manies` WHERE `has_manies`\\.`id` = \\? AND \\(\\(`has_manies`\\.`id` = 1\\)\\) ORDER BY `has_manies`\\.`id` ASC LIMIT 1").WillReturnRows(rows) - dbc.ExpectQuery("SELECT \\* FROM `ones` WHERE \\(`has_many_id` IN \\(\\?\\)\\) ORDER BY `ones`\\.`id` ASC").WillReturnRows(rows) + dbc.ExpectQuery("SELECT * FROM `has_manies` WHERE (`has_manies`.`id` = ?) ORDER BY `has_manies`.`id` ASC LIMIT 1").WithArgs(1).WillReturnRows(rows) + dbc.ExpectQuery("SELECT * FROM `ones` WHERE (`has_many_id` IN (?)) ORDER BY `ones`.`id` ASC").WillReturnRows(rows) model := HasMany{ - Model: db_repo.Model{ + Model: dbRepo.Model{ Id: id1, }, Manies: []*Ones{}, @@ -597,15 +600,15 @@ func TestRepository_UpdateHasManyNoRelation(t *testing.T) { } func TestRepository_Delete(t *testing.T) { - dbc, repo := getMocks(t, myTestModel) + dbc, repo := getMocks[*MyTestModel](t, myTestModel, false) result := goSqlMock.NewResult(0, 1) dbc.ExpectBegin() - dbc.ExpectExec("DELETE FROM `my_test_models` WHERE `my_test_models`\\.`id` = \\?").WithArgs(id1).WillReturnResult(result) + dbc.ExpectExec("DELETE FROM `my_test_models` WHERE `my_test_models`.`id` = ?").WithArgs(id1).WillReturnResult(result) dbc.ExpectCommit() model := MyTestModel{ - Model: db_repo.Model{ + Model: dbRepo.Model{ Id: id1, }, } @@ -620,18 +623,18 @@ func TestRepository_Delete(t *testing.T) { } func TestRepository_DeleteManyToManyNoRelation(t *testing.T) { - dbc, repo := getMocks(t, manyToMany) + dbc, repo := getMocks[*ManyToMany](t, manyToMany, false) result := goSqlMock.NewResult(0, 1) dbc.ExpectBegin() - dbc.ExpectExec("DELETE FROM `many_of_manies` WHERE \\(`many_to_many_id` IN \\(\\?\\)\\)").WithArgs(id1).WillReturnResult(result) + dbc.ExpectExec("DELETE FROM `many_of_manies` WHERE (`many_to_many_id` IN (?))").WithArgs(id1).WillReturnResult(result) dbc.ExpectCommit() dbc.ExpectBegin() - dbc.ExpectExec("DELETE FROM `many_to_manies` WHERE `many_to_manies`\\.`id` = \\?").WithArgs(id1).WillReturnResult(result) + dbc.ExpectExec("DELETE FROM `many_to_manies` WHERE `many_to_manies`.`id` = ?").WithArgs(id1).WillReturnResult(result) dbc.ExpectCommit() model := ManyToMany{ - Model: db_repo.Model{ + Model: dbRepo.Model{ Id: id1, }, } @@ -646,23 +649,23 @@ func TestRepository_DeleteManyToManyNoRelation(t *testing.T) { } func TestRepository_DeleteManyToMany(t *testing.T) { - dbc, repo := getMocks(t, manyToMany) + dbc, repo := getMocks[*ManyToMany](t, manyToMany, false) result := goSqlMock.NewResult(0, 1) dbc.ExpectBegin() - dbc.ExpectExec("DELETE FROM `many_of_manies` WHERE \\(`many_to_many_id` IN \\(\\?\\)\\)").WithArgs(id1).WillReturnResult(result) + dbc.ExpectExec("DELETE FROM `many_of_manies` WHERE (`many_to_many_id` IN (?))").WithArgs(id1).WillReturnResult(result) dbc.ExpectCommit() dbc.ExpectBegin() - dbc.ExpectExec("DELETE FROM `many_to_manies` WHERE `many_to_manies`\\.`id` = \\?").WithArgs(id1).WillReturnResult(result) + dbc.ExpectExec("DELETE FROM `many_to_manies` WHERE `many_to_manies`.`id` = ?").WithArgs(id1).WillReturnResult(result) dbc.ExpectCommit() model := ManyToMany{ - Model: db_repo.Model{ + Model: dbRepo.Model{ Id: id1, }, RelModel: []MyTestModel{ { - Model: db_repo.Model{ + Model: dbRepo.Model{ Id: id42, }, }, @@ -679,15 +682,15 @@ func TestRepository_DeleteManyToMany(t *testing.T) { } func TestRepository_DeleteManyToOneNoRelation(t *testing.T) { - dbc, repo := getMocks(t, oneOfMany) + dbc, repo := getMocks[*OneOfMany](t, oneOfMany, false) result := goSqlMock.NewResult(0, 1) dbc.ExpectBegin() - dbc.ExpectExec("DELETE FROM `one_of_manies` WHERE `one_of_manies`\\.`id` = \\?").WithArgs(id1).WillReturnResult(result) + dbc.ExpectExec("DELETE FROM `one_of_manies` WHERE `one_of_manies`.`id` = ?").WithArgs(id1).WillReturnResult(result) dbc.ExpectCommit() model := OneOfMany{ - Model: db_repo.Model{ + Model: dbRepo.Model{ Id: id1, }, } @@ -702,19 +705,19 @@ func TestRepository_DeleteManyToOneNoRelation(t *testing.T) { } func TestRepository_DeleteManyToOne(t *testing.T) { - dbc, repo := getMocks(t, oneOfMany) + dbc, repo := getMocks[*OneOfMany](t, oneOfMany, false) result := goSqlMock.NewResult(0, 1) dbc.ExpectBegin() - dbc.ExpectExec("DELETE FROM `one_of_manies` WHERE `one_of_manies`\\.`id` = \\?").WithArgs(id1).WillReturnResult(result) + dbc.ExpectExec("DELETE FROM `one_of_manies` WHERE `one_of_manies`.`id` = ?").WithArgs(id1).WillReturnResult(result) dbc.ExpectCommit() model := OneOfMany{ - Model: db_repo.Model{ + Model: dbRepo.Model{ Id: id1, }, MyTestModel: &MyTestModel{ - Model: db_repo.Model{ + Model: dbRepo.Model{ Id: id42, }, }, @@ -731,28 +734,28 @@ func TestRepository_DeleteManyToOne(t *testing.T) { } func TestRepository_DeleteHasMany(t *testing.T) { - dbc, repo := getMocks(t, hasMany) + dbc, repo := getMocks[*HasMany](t, hasMany, false) childResult := goSqlMock.NewResult(0, 0) parentResult := goSqlMock.NewResult(0, 1) dbc.ExpectExec("DELETE FROM manies WHERE has_many_id = 1").WillReturnResult(childResult) dbc.ExpectBegin() - dbc.ExpectExec("DELETE FROM `has_manies` WHERE `has_manies`\\.`id` = ?").WithArgs(id1).WillReturnResult(parentResult) + dbc.ExpectExec("DELETE FROM `has_manies` WHERE `has_manies`.`id` = ?").WithArgs(id1).WillReturnResult(parentResult) dbc.ExpectCommit() model := HasMany{ - Model: db_repo.Model{ + Model: dbRepo.Model{ Id: id1, }, Manies: []*Ones{ { - Model: db_repo.Model{ + Model: dbRepo.Model{ Id: id42, }, }, { - Model: db_repo.Model{ + Model: dbRepo.Model{ Id: id24, }, }, @@ -769,18 +772,18 @@ func TestRepository_DeleteHasMany(t *testing.T) { } func TestRepository_DeleteHasManyNoRelation(t *testing.T) { - dbc, repo := getMocks(t, hasMany) + dbc, repo := getMocks[*HasMany](t, hasMany, false) childResult := goSqlMock.NewResult(0, 0) parentResult := goSqlMock.NewResult(0, 1) dbc.ExpectExec("DELETE FROM manies WHERE has_many_id = 1").WillReturnResult(childResult) dbc.ExpectBegin() - dbc.ExpectExec("DELETE FROM `has_manies` WHERE `has_manies`\\.`id` = ?").WithArgs(id1).WillReturnResult(parentResult) + dbc.ExpectExec("DELETE FROM `has_manies` WHERE `has_manies`.`id` = ?").WithArgs(id1).WillReturnResult(parentResult) dbc.ExpectCommit() model := HasMany{ - Model: db_repo.Model{ + Model: dbRepo.Model{ Id: id1, }, Manies: []*Ones{}, @@ -795,12 +798,33 @@ func TestRepository_DeleteHasManyNoRelation(t *testing.T) { assert.NoError(t, err) } -func getMocks(t *testing.T, whichMetadata string) (goSqlMock.Sqlmock, db_repo.Repository) { +func queryMatcher(useRegexMatcher bool) goSqlMock.QueryMatcher { + whiteSpace := regexp.MustCompile(`\s{2,}`) + + return goSqlMock.QueryMatcherFunc(func(expectedSQL string, actualSQL string) error { + if useRegexMatcher { + return goSqlMock.QueryMatcherRegexp.Match(expectedSQL, actualSQL) + } + + expectedSQL = whiteSpace.ReplaceAllString(expectedSQL, " ") + actualSQL = whiteSpace.ReplaceAllString(actualSQL, " ") + + if expectedSQL != actualSQL { + fmt.Printf("Failed to match\n\t%s\nwith\n\t%s\n", expectedSQL, actualSQL) + + return fmt.Errorf(`could not match actual sql: "%s" with expected sql "%s"`, actualSQL, expectedSQL) + } + + return nil + }) +} + +func getMocks[M dbRepo.ModelBased[uint]](t *testing.T, whichMetadata string, useRegexMatcher bool) (goSqlMock.Sqlmock, dbRepo.Repository[uint, M]) { logger := logMocks.NewLoggerMockedAll() tracer := tracing.NewNoopTracer() - db, clientMock, _ := goSqlMock.New() - orm, err := db_repo.NewOrmWithInterfaces(db, db_repo.OrmSettings{ + db, clientMock, _ := goSqlMock.New(goSqlMock.QueryMatcherOption(queryMatcher(useRegexMatcher))) + orm, err := dbRepo.NewOrmWithInterfaces(db, dbRepo.OrmSettings{ Driver: "mysql", }) if err != nil { @@ -814,18 +838,19 @@ func getMocks(t *testing.T, whichMetadata string) (goSqlMock.Sqlmock, db_repo.Re t.Errorf("couldn't find metadata named: %s", whichMetadata) } - repo := db_repo.NewWithInterfaces(logger, tracer, orm, testClock, metadata) + repo := dbRepo.NewWithInterfaces[uint, M](logger, tracer, orm, testClock, metadata, dbRepo.CreateModel[M]) return clientMock, repo } -func getTimedMocks(t *testing.T, time time.Time, whichMetadata string) (goSqlMock.Sqlmock, db_repo.Repository) { +func getTimedMocks[M dbRepo.ModelBased[uint]](t *testing.T, time time.Time, whichMetadata string, useRegexMatcher bool) (goSqlMock.Sqlmock, dbRepo.Repository[uint, M]) { logger := logMocks.NewLoggerMockedAll() tracer := tracing.NewNoopTracer() - db, clientMock, _ := goSqlMock.New() + db, clientMock, err := goSqlMock.New(goSqlMock.QueryMatcherOption(queryMatcher(useRegexMatcher))) + assert.NoError(t, err) - orm, err := db_repo.NewOrmWithInterfaces(db, db_repo.OrmSettings{ + orm, err := dbRepo.NewOrmWithInterfaces(db, dbRepo.OrmSettings{ Driver: "mysql", }) if err != nil { @@ -839,7 +864,7 @@ func getTimedMocks(t *testing.T, time time.Time, whichMetadata string) (goSqlMoc t.Errorf("couldn't find metadata named: %s", whichMetadata) } - repo := db_repo.NewWithInterfaces(logger, tracer, orm, testClock, metadata) + repo := dbRepo.NewWithInterfaces[uint, M](logger, tracer, orm, testClock, metadata, dbRepo.CreateModel[M]) return clientMock, repo } diff --git a/pkg/dispatcher/repository_db.go b/pkg/dispatcher/repository_db.go index 0141a2129..e6c929b5e 100644 --- a/pkg/dispatcher/repository_db.go +++ b/pkg/dispatcher/repository_db.go @@ -7,28 +7,29 @@ import ( "github.com/justtrackio/gosoline/pkg/cfg" "github.com/justtrackio/gosoline/pkg/db-repo" "github.com/justtrackio/gosoline/pkg/log" + "github.com/justtrackio/gosoline/pkg/mdl" ) -type Repository struct { - db_repo.Repository +type Repository[K mdl.PossibleIdentifier, M db_repo.ModelBased[K]] struct { + db_repo.Repository[K, M] dispatcher Dispatcher logger log.Logger } -func NewRepository(ctx context.Context, config cfg.Config, logger log.Logger, repo db_repo.Repository) (db_repo.Repository, error) { +func NewRepository[K mdl.PossibleIdentifier, M db_repo.ModelBased[K]](ctx context.Context, config cfg.Config, logger log.Logger, repo db_repo.Repository[K, M]) (db_repo.Repository[K, M], error) { disp, err := ProvideDispatcher(ctx, config, logger) if err != nil { return nil, fmt.Errorf("can not provide dispatcher: %w", err) } - return &Repository{ + return &Repository[K, M]{ Repository: repo, dispatcher: disp, logger: logger, }, nil } -func (r Repository) Create(ctx context.Context, value db_repo.ModelBased) error { +func (r Repository[K, M]) Create(ctx context.Context, value M) error { err := r.Repository.Create(ctx, value) if err != nil { return err @@ -46,7 +47,7 @@ func (r Repository) Create(ctx context.Context, value db_repo.ModelBased) error return nil } -func (r Repository) Update(ctx context.Context, value db_repo.ModelBased) error { +func (r Repository[K, M]) Update(ctx context.Context, value M) error { err := r.Repository.Update(ctx, value) if err != nil { return err @@ -64,7 +65,7 @@ func (r Repository) Update(ctx context.Context, value db_repo.ModelBased) error return nil } -func (r Repository) Delete(ctx context.Context, value db_repo.ModelBased) error { +func (r Repository[K, M]) Delete(ctx context.Context, value M) error { err := r.Repository.Delete(ctx, value) if err != nil { return err diff --git a/pkg/fixtures/named.go b/pkg/fixtures/named.go index 174531048..fbd6c1ebe 100644 --- a/pkg/fixtures/named.go +++ b/pkg/fixtures/named.go @@ -97,7 +97,7 @@ func GetValueId(value interface{}) (interface{}, bool) { return GetValueId(kvValue.Value) } - if identifiable, ok := value.(mdl.Identifiable); ok { + if identifiable, ok := value.(mdl.Identifiable[uint]); ok { return mdl.EmptyIfNil(identifiable.GetId()), true } diff --git a/pkg/fixtures/writer_mysql_orm.go b/pkg/fixtures/writer_mysql_orm.go index be2c783a0..265ffb9f5 100644 --- a/pkg/fixtures/writer_mysql_orm.go +++ b/pkg/fixtures/writer_mysql_orm.go @@ -3,6 +3,7 @@ package fixtures import ( "context" "fmt" + "reflect" "github.com/justtrackio/gosoline/pkg/cfg" "github.com/justtrackio/gosoline/pkg/db-repo" @@ -12,7 +13,7 @@ import ( type mysqlOrmFixtureWriter struct { logger log.Logger metadata *db_repo.Metadata - repo db_repo.Repository + repo db_repo.ConfigurableRepository[uint, db_repo.ModelBased[uint]] purger *mysqlPurger } @@ -25,7 +26,7 @@ func MysqlOrmFixtureWriterFactory(metadata *db_repo.Metadata) FixtureWriterFacto Metadata: *metadata, } - repo, err := db_repo.New(config, logger, settings) + repo, err := db_repo.New[uint, db_repo.ModelBased[uint]](config, logger, settings) if err != nil { return nil, fmt.Errorf("can not create repo: %w", err) } @@ -39,7 +40,7 @@ func MysqlOrmFixtureWriterFactory(metadata *db_repo.Metadata) FixtureWriterFacto } } -func NewMysqlFixtureWriterWithInterfaces(logger log.Logger, metadata *db_repo.Metadata, repo db_repo.Repository, purger *mysqlPurger) FixtureWriter { +func NewMysqlFixtureWriterWithInterfaces(logger log.Logger, metadata *db_repo.Metadata, repo db_repo.ConfigurableRepository[uint, db_repo.ModelBased[uint]], purger *mysqlPurger) FixtureWriter { return &mysqlOrmFixtureWriter{ logger: logger, metadata: metadata, @@ -63,7 +64,11 @@ func (m *mysqlOrmFixtureWriter) Purge(ctx context.Context) error { func (m *mysqlOrmFixtureWriter) Write(ctx context.Context, fs *FixtureSet) error { for _, item := range fs.Fixtures { - model := item.(db_repo.ModelBased) + model := item.(db_repo.ModelBased[uint]) + + m.repo.SetModelSource(func() db_repo.ModelBased[uint] { + return createFromType(model) + }) err := m.repo.Update(ctx, model) if err != nil { @@ -75,3 +80,18 @@ func (m *mysqlOrmFixtureWriter) Write(ctx context.Context, fs *FixtureSet) error return nil } + +func createFromType[T any](model T) T { + modelType := reflect.TypeOf(model) + + switch modelType.Kind() { + case reflect.Pointer: + return reflect.New(modelType.Elem()).Interface().(T) + + case reflect.Map: + return reflect.MakeMap(modelType).Interface().(T) + + default: + return *reflect.New(modelType.Elem()).Interface().(*T) + } +} diff --git a/pkg/funk/slice.go b/pkg/funk/slice.go index ad53567cc..77415ed2a 100644 --- a/pkg/funk/slice.go +++ b/pkg/funk/slice.go @@ -4,11 +4,14 @@ import ( "fmt" "reflect" - "github.com/justtrackio/gosoline/pkg/mdl" "golang.org/x/exp/maps" "golang.org/x/exp/slices" ) +type Keyed interface { + GetKey() string +} + // CastSlice casts a []any slice to the given type. // The parameter sliceType is required to correctly infer the target type. func CastSlice[T any, I ~[]any](sl I) ([]T, error) { @@ -108,7 +111,7 @@ func Difference[S ~[]T, T comparable](left, right S) (inLeft, inRight []T) { return inLeft, inRight } -func DifferenceKeyed[S1 ~[]T1, S2 ~[]T2, T1, T2 mdl.Keyed](left S1, right S2) (inLeft S1, inRight S2) { +func DifferenceKeyed[S1 ~[]T1, S2 ~[]T2, T1, T2 Keyed](left S1, right S2) (inLeft S1, inRight S2) { inLeftS, inRightS := DifferenceMaps(KeyedToMap(left), KeyedToMap(right)) return maps.Values(inLeftS), maps.Values(inRightS) @@ -191,11 +194,11 @@ func Intersect[S ~[]T, T comparable](sl1, sl2 S) []T { return maps.Keys(result) } -func IntersectKeyed[S ~[]T, T mdl.Keyed](s1, s2 S) S { +func IntersectKeyed[S ~[]T, T Keyed](s1, s2 S) S { return maps.Values(IntersectMaps(KeyedToMap(s1), KeyedToMap(s2))) } -func KeyedToMap[S ~[]T, T mdl.Keyed](sl S) map[string]T { +func KeyedToMap[S ~[]T, T Keyed](sl S) map[string]T { out := make(map[string]T, len(sl)) for _, item := range sl { diff --git a/pkg/funk/slice_test.go b/pkg/funk/slice_test.go index 9790f9df5..405afb448 100644 --- a/pkg/funk/slice_test.go +++ b/pkg/funk/slice_test.go @@ -3,10 +3,9 @@ package funk_test import ( "testing" - "golang.org/x/exp/slices" - "github.com/justtrackio/gosoline/pkg/funk" "github.com/stretchr/testify/assert" + "golang.org/x/exp/slices" ) func TestCastSlice(t *testing.T) { diff --git a/pkg/guard/guard_test.go b/pkg/guard/guard_test.go index 87ca26ad5..ca9069b8f 100644 --- a/pkg/guard/guard_test.go +++ b/pkg/guard/guard_test.go @@ -4,13 +4,11 @@ import ( "context" "testing" - "github.com/stretchr/testify/assert" - "github.com/justtrackio/gosoline/pkg/guard" + "github.com/justtrackio/gosoline/pkg/guard/mocks" "github.com/selm0/ladon" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - - "github.com/justtrackio/gosoline/pkg/guard/mocks" ) // Test LadonGuard::GetPolicies diff --git a/pkg/httpserver/auth/config_google.go b/pkg/httpserver/auth/config_google.go index 9d00247c5..694146438 100644 --- a/pkg/httpserver/auth/config_google.go +++ b/pkg/httpserver/auth/config_google.go @@ -7,12 +7,11 @@ import ( "regexp" "sync" - "golang.org/x/exp/slices" - "github.com/gin-gonic/gin" "github.com/justtrackio/gosoline/pkg/cfg" "github.com/justtrackio/gosoline/pkg/log" "github.com/pkg/errors" + "golang.org/x/exp/slices" "google.golang.org/api/oauth2/v2" "google.golang.org/api/option" ) diff --git a/pkg/httpserver/auth/config_key.go b/pkg/httpserver/auth/config_key.go index 7e5bbb5d3..8feabf5cb 100644 --- a/pkg/httpserver/auth/config_key.go +++ b/pkg/httpserver/auth/config_key.go @@ -4,12 +4,11 @@ import ( "fmt" "net/http" - "golang.org/x/exp/slices" - "github.com/gin-gonic/gin" "github.com/justtrackio/gosoline/pkg/cfg" "github.com/justtrackio/gosoline/pkg/funk" "github.com/justtrackio/gosoline/pkg/log" + "golang.org/x/exp/slices" ) const ( diff --git a/pkg/httpserver/crud/create.go b/pkg/httpserver/crud/create.go index b394b8129..4592bd513 100644 --- a/pkg/httpserver/crud/create.go +++ b/pkg/httpserver/crud/create.go @@ -7,18 +7,20 @@ import ( "github.com/gin-gonic/gin" "github.com/justtrackio/gosoline/pkg/db" + dbRepo "github.com/justtrackio/gosoline/pkg/db-repo" "github.com/justtrackio/gosoline/pkg/httpserver" "github.com/justtrackio/gosoline/pkg/log" + "github.com/justtrackio/gosoline/pkg/mdl" "github.com/justtrackio/gosoline/pkg/validation" ) -type createHandler struct { +type createHandler[I any, O any, K mdl.PossibleIdentifier, M dbRepo.ModelBased[K]] struct { logger log.Logger - transformer CreateHandler + transformer CreateHandler[I, O, K, M] } -func NewCreateHandler(logger log.Logger, transformer CreateHandler) gin.HandlerFunc { - ch := createHandler{ +func NewCreateHandler[I any, O any, K mdl.PossibleIdentifier, M dbRepo.ModelBased[K]](logger log.Logger, transformer CreateHandler[I, O, K, M]) gin.HandlerFunc { + ch := createHandler[I, O, K, M]{ transformer: transformer, logger: logger, } @@ -26,13 +28,14 @@ func NewCreateHandler(logger log.Logger, transformer CreateHandler) gin.HandlerF return httpserver.CreateJsonHandler(ch) } -func (ch createHandler) GetInput() interface{} { - return ch.transformer.GetCreateInput() +func (ch createHandler[I, O, K, M]) GetInput() interface{} { + var input I + + return &input } -func (ch createHandler) Handle(ctx context.Context, request *httpserver.Request) (*httpserver.Response, error) { - model := ch.transformer.GetModel() - err := ch.transformer.TransformCreate(ctx, request.Body, model) +func (ch createHandler[I, O, K, M]) Handle(ctx context.Context, request *httpserver.Request) (*httpserver.Response, error) { + model, err := ch.transformer.TransformCreate(ctx, request.Body.(*I)) if err != nil { return nil, err } @@ -52,9 +55,7 @@ func (ch createHandler) Handle(ctx context.Context, request *httpserver.Request) return nil, err } - reload := ch.transformer.GetModel() - err = repo.Read(ctx, model.GetId(), reload) - + reload, err := repo.Read(ctx, *model.GetId()) if err != nil { return nil, err } diff --git a/pkg/httpserver/crud/crud_test.go b/pkg/httpserver/crud/crud_test.go index f839491c3..821e335df 100644 --- a/pkg/httpserver/crud/crud_test.go +++ b/pkg/httpserver/crud/crud_test.go @@ -7,19 +7,18 @@ import ( "testing" "time" - "github.com/justtrackio/gosoline/pkg/db-repo" + dbRepo "github.com/justtrackio/gosoline/pkg/db-repo" + dbRepoMocks "github.com/justtrackio/gosoline/pkg/db-repo/mocks" "github.com/justtrackio/gosoline/pkg/httpserver" "github.com/justtrackio/gosoline/pkg/httpserver/crud" - "github.com/justtrackio/gosoline/pkg/httpserver/crud/mocks" logMocks "github.com/justtrackio/gosoline/pkg/log/mocks" "github.com/justtrackio/gosoline/pkg/mdl" "github.com/justtrackio/gosoline/pkg/validation" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/mock" ) type Model struct { - db_repo.Model + dbRepo.Model Name *string `json:"name"` } @@ -39,86 +38,60 @@ type UpdateInput struct { } type Handler struct { - Repo *mocks.Repository + Repo *dbRepoMocks.Repository[uint, *Model] } -func (h Handler) GetRepository() crud.Repository { +func (h Handler) GetRepository() dbRepo.Repository[uint, *Model] { return h.Repo } -func (h Handler) GetModel() db_repo.ModelBased { - return &Model{} -} - -func (h Handler) GetCreateInput() interface{} { - return &CreateInput{} -} - -func (h Handler) GetUpdateInput() interface{} { - return &UpdateInput{} -} - -func (h Handler) TransformCreate(_ctx context.Context, inp interface{}, model db_repo.ModelBased) (err error) { - input := inp.(*CreateInput) - m := model.(*Model) - - m.Name = input.Name - - return nil +func (h Handler) TransformCreate(_ context.Context, inp *CreateInput) (*Model, error) { + return &Model{ + Name: inp.Name, + }, nil } -func (h Handler) TransformUpdate(_ context.Context, inp interface{}, model db_repo.ModelBased) (err error) { - input := inp.(*UpdateInput) - m := model.(*Model) - - m.Name = input.Name +func (h Handler) TransformUpdate(_ context.Context, inp *UpdateInput, model *Model) (*Model, error) { + model.Name = inp.Name - return nil + return model, nil } -func (h Handler) TransformOutput(ctx context.Context, model db_repo.ModelBased, _ string) (interface{}, error) { - m := model.(*Model) - - out := &Output{ - Id: m.Id, - Name: m.Name, - UpdatedAt: m.UpdatedAt, - CreatedAt: m.CreatedAt, +func (h Handler) TransformOutput(_ context.Context, model *Model, _ string) (output Output, err error) { + out := Output{ + Id: model.Id, + Name: model.Name, + UpdatedAt: model.UpdatedAt, + CreatedAt: model.CreatedAt, } return out, nil } -func (h Handler) List(_ context.Context, _ *db_repo.QueryBuilder, _ string) (interface{}, error) { +func (h Handler) List(_ context.Context, _ *dbRepo.QueryBuilder, _ string) (out []Output, err error) { date, err := time.Parse(time.RFC3339, "2006-01-02T15:04:05Z") if err != nil { panic(err) } - return []Model{ + return []Output{ { - Model: db_repo.Model{ - Id: mdl.Box(uint(1)), - Timestamps: db_repo.Timestamps{ - UpdatedAt: mdl.Box(date), - CreatedAt: mdl.Box(date), - }, - }, - Name: mdl.Box("foobar"), + Id: mdl.Box(uint(1)), + Name: mdl.Box("foobar"), + UpdatedAt: mdl.Box(date), + CreatedAt: mdl.Box(date), }, }, nil } func NewTransformer() Handler { - repo := new(mocks.Repository) + repo := new(dbRepoMocks.Repository[uint, *Model]) return Handler{ Repo: repo, } } -var id1 = mdl.Box(uint(1)) - func TestCreateHandler_Handle(t *testing.T) { model := &Model{ Name: mdl.Box("foobar"), @@ -127,19 +100,21 @@ func TestCreateHandler_Handle(t *testing.T) { logger := logMocks.NewLoggerMockedAll() transformer := NewTransformer() - transformer.Repo.On("Create", mock.AnythingOfType("context.backgroundCtx"), model).Run(func(args mock.Arguments) { - model := args.Get(1).(*Model) - model.Id = mdl.Box(uint(1)) - }).Return(nil) - transformer.Repo.On("Read", mock.AnythingOfType("context.backgroundCtx"), mdl.Box(uint(1)), &Model{}).Run(func(args mock.Arguments) { - model := args.Get(2).(*Model) - model.Id = mdl.Box(uint(1)) - model.Name = mdl.Box("foobar") - model.UpdatedAt = &time.Time{} - model.CreatedAt = &time.Time{} + transformer.Repo.EXPECT().Create(context.Background(), model).Run(func(ctx context.Context, value *Model) { + value.Id = mdl.Box(uint(1)) }).Return(nil) + transformer.Repo.EXPECT().Read(context.Background(), uint(1)).Return(&Model{ + Model: dbRepo.Model{ + Id: mdl.Box(uint(1)), + Timestamps: dbRepo.Timestamps{ + UpdatedAt: &time.Time{}, + CreatedAt: &time.Time{}, + }, + }, + Name: mdl.Box("foobar"), + }, nil) - handler := crud.NewCreateHandler(logger, transformer) + handler := crud.NewCreateHandler[CreateInput, Output, uint, *Model](logger, transformer) body := `{"name": "foobar"}` response := httpserver.HttpTest("POST", "/create", "/create", body, handler) @@ -158,11 +133,11 @@ func TestCreateHandler_Handle_ValidationError(t *testing.T) { logger := logMocks.NewLoggerMockedAll() transformer := NewTransformer() - transformer.Repo.On("Create", mock.AnythingOfType("context.backgroundCtx"), model).Return(&validation.Error{ + transformer.Repo.EXPECT().Create(context.Background(), model).Return(&validation.Error{ Errors: []error{fmt.Errorf("invalid foobar")}, }) - handler := crud.NewCreateHandler(logger, transformer) + handler := crud.NewCreateHandler[CreateInput, Output, uint, *Model](logger, transformer) body := `{"name": "foobar"}` response := httpserver.HttpTest("POST", "/create", "/create", body, handler) @@ -174,19 +149,20 @@ func TestCreateHandler_Handle_ValidationError(t *testing.T) { } func TestReadHandler_Handle(t *testing.T) { - model := &Model{} - logger := logMocks.NewLoggerMockedAll() transformer := NewTransformer() - transformer.Repo.On("Read", mock.AnythingOfType("context.backgroundCtx"), mdl.Box(uint(1)), model).Run(func(args mock.Arguments) { - model := args.Get(2).(*Model) - model.Id = mdl.Box(uint(1)) - model.Name = mdl.Box("foobar") - model.UpdatedAt = &time.Time{} - model.CreatedAt = &time.Time{} - }).Return(nil) + transformer.Repo.EXPECT().Read(context.Background(), uint(1)).Return(&Model{ + Model: dbRepo.Model{ + Id: mdl.Box(uint(1)), + Timestamps: dbRepo.Timestamps{ + UpdatedAt: &time.Time{}, + CreatedAt: &time.Time{}, + }, + }, + Name: mdl.Box("foobar"), + }, nil) - handler := crud.NewReadHandler(logger, transformer) + handler := crud.NewReadHandler[Output, uint, *Model](logger, transformer) response := httpserver.HttpTest("GET", "/:id", "/1", "", handler) @@ -197,11 +173,10 @@ func TestReadHandler_Handle(t *testing.T) { } func TestUpdateHandler_Handle(t *testing.T) { - readModel := &Model{} updateModel := &Model{ - Model: db_repo.Model{ + Model: dbRepo.Model{ Id: mdl.Box(uint(1)), - Timestamps: db_repo.Timestamps{ + Timestamps: dbRepo.Timestamps{ UpdatedAt: &time.Time{}, CreatedAt: &time.Time{}, }, @@ -212,16 +187,19 @@ func TestUpdateHandler_Handle(t *testing.T) { logger := logMocks.NewLoggerMockedAll() transformer := NewTransformer() - transformer.Repo.On("Update", mock.AnythingOfType("context.backgroundCtx"), updateModel).Return(nil) - transformer.Repo.On("Read", mock.AnythingOfType("context.backgroundCtx"), mdl.Box(uint(1)), readModel).Run(func(args mock.Arguments) { - model := args.Get(2).(*Model) - model.Id = mdl.Box(uint(1)) - model.Name = mdl.Box("updated") - model.UpdatedAt = &time.Time{} - model.CreatedAt = &time.Time{} - }).Return(nil) + transformer.Repo.EXPECT().Update(context.Background(), updateModel).Return(nil) + transformer.Repo.EXPECT().Read(context.Background(), uint(1)).Return(&Model{ + Model: dbRepo.Model{ + Id: mdl.Box(uint(1)), + Timestamps: dbRepo.Timestamps{ + UpdatedAt: &time.Time{}, + CreatedAt: &time.Time{}, + }, + }, + Name: mdl.Box("updated"), + }, nil) - handler := crud.NewUpdateHandler(logger, transformer) + handler := crud.NewUpdateHandler[UpdateInput, Output, uint, *Model](logger, transformer) body := `{"name": "updated"}` response := httpserver.HttpTest("PUT", "/:id", "/1", body, handler) @@ -233,11 +211,10 @@ func TestUpdateHandler_Handle(t *testing.T) { } func TestUpdateHandler_Handle_ValidationError(t *testing.T) { - readModel := &Model{} updateModel := &Model{ - Model: db_repo.Model{ + Model: dbRepo.Model{ Id: mdl.Box(uint(1)), - Timestamps: db_repo.Timestamps{ + Timestamps: dbRepo.Timestamps{ UpdatedAt: &time.Time{}, CreatedAt: &time.Time{}, }, @@ -248,18 +225,21 @@ func TestUpdateHandler_Handle_ValidationError(t *testing.T) { logger := logMocks.NewLoggerMockedAll() transformer := NewTransformer() - transformer.Repo.On("Update", mock.AnythingOfType("context.backgroundCtx"), updateModel).Return(&validation.Error{ + transformer.Repo.EXPECT().Update(context.Background(), updateModel).Return(&validation.Error{ Errors: []error{fmt.Errorf("invalid foobar")}, }) - transformer.Repo.On("Read", mock.AnythingOfType("context.backgroundCtx"), mdl.Box(uint(1)), readModel).Run(func(args mock.Arguments) { - model := args.Get(2).(*Model) - model.Id = mdl.Box(uint(1)) - model.Name = mdl.Box("updated") - model.UpdatedAt = &time.Time{} - model.CreatedAt = &time.Time{} - }).Return(nil) + transformer.Repo.EXPECT().Read(context.Background(), uint(1)).Return(&Model{ + Model: dbRepo.Model{ + Id: mdl.Box(uint(1)), + Timestamps: dbRepo.Timestamps{ + UpdatedAt: &time.Time{}, + CreatedAt: &time.Time{}, + }, + }, + Name: mdl.Box("updated"), + }, nil) - handler := crud.NewUpdateHandler(logger, transformer) + handler := crud.NewUpdateHandler[UpdateInput, Output, uint, *Model](logger, transformer) body := `{"name": "updated"}` response := httpserver.HttpTest("PUT", "/:id", "/1", body, handler) @@ -271,11 +251,10 @@ func TestUpdateHandler_Handle_ValidationError(t *testing.T) { } func TestDeleteHandler_Handle(t *testing.T) { - model := &Model{} deleteModel := &Model{ - Model: db_repo.Model{ - Id: id1, - Timestamps: db_repo.Timestamps{ + Model: dbRepo.Model{ + Id: mdl.Box(uint(1)), + Timestamps: dbRepo.Timestamps{ UpdatedAt: &time.Time{}, CreatedAt: &time.Time{}, }, @@ -285,16 +264,20 @@ func TestDeleteHandler_Handle(t *testing.T) { logger := logMocks.NewLoggerMockedAll() transformer := NewTransformer() - transformer.Repo.On("Read", mock.AnythingOfType("context.backgroundCtx"), mock.AnythingOfType("*uint"), model).Run(func(args mock.Arguments) { - model := args.Get(2).(*Model) - model.Id = id1 - model.Name = mdl.Box("foobar") - model.UpdatedAt = &time.Time{} - model.CreatedAt = &time.Time{} - }).Return(nil) - transformer.Repo.On("Delete", mock.AnythingOfType("context.backgroundCtx"), deleteModel).Return(nil) - handler := crud.NewDeleteHandler(logger, transformer) + transformer.Repo.EXPECT().Read(context.Background(), uint(1)).Return(&Model{ + Model: dbRepo.Model{ + Id: mdl.Box(uint(1)), + Timestamps: dbRepo.Timestamps{ + UpdatedAt: &time.Time{}, + CreatedAt: &time.Time{}, + }, + }, + Name: mdl.Box("foobar"), + }, nil) + transformer.Repo.EXPECT().Delete(context.Background(), deleteModel).Return(nil) + + handler := crud.NewDeleteHandler[Output, uint, *Model](logger, transformer) response := httpserver.HttpTest("DELETE", "/:id", "/1", "", handler) @@ -305,11 +288,10 @@ func TestDeleteHandler_Handle(t *testing.T) { } func TestDeleteHandler_Handle_ValidationError(t *testing.T) { - model := &Model{} deleteModel := &Model{ - Model: db_repo.Model{ - Id: id1, - Timestamps: db_repo.Timestamps{ + Model: dbRepo.Model{ + Id: mdl.Box(uint(1)), + Timestamps: dbRepo.Timestamps{ UpdatedAt: &time.Time{}, CreatedAt: &time.Time{}, }, @@ -319,18 +301,22 @@ func TestDeleteHandler_Handle_ValidationError(t *testing.T) { logger := logMocks.NewLoggerMockedAll() transformer := NewTransformer() - transformer.Repo.On("Read", mock.AnythingOfType("context.backgroundCtx"), mock.AnythingOfType("*uint"), model).Run(func(args mock.Arguments) { - model := args.Get(2).(*Model) - model.Id = id1 - model.Name = mdl.Box("foobar") - model.UpdatedAt = &time.Time{} - model.CreatedAt = &time.Time{} - }).Return(nil) - transformer.Repo.On("Delete", mock.AnythingOfType("context.backgroundCtx"), deleteModel).Return(&validation.Error{ + + transformer.Repo.EXPECT().Read(context.Background(), uint(1)).Return(&Model{ + Model: dbRepo.Model{ + Id: mdl.Box(uint(1)), + Timestamps: dbRepo.Timestamps{ + UpdatedAt: &time.Time{}, + CreatedAt: &time.Time{}, + }, + }, + Name: mdl.Box("foobar"), + }, nil) + transformer.Repo.EXPECT().Delete(context.Background(), deleteModel).Return(&validation.Error{ Errors: []error{fmt.Errorf("invalid foobar")}, }) - handler := crud.NewDeleteHandler(logger, transformer) + handler := crud.NewDeleteHandler[Output, uint, *Model](logger, transformer) response := httpserver.HttpTest("DELETE", "/:id", "/1", "", handler) @@ -343,30 +329,31 @@ func TestDeleteHandler_Handle_ValidationError(t *testing.T) { func TestListHandler_Handle(t *testing.T) { logger := logMocks.NewLoggerMockedAll() transformer := NewTransformer() - handler := crud.NewListHandler(logger, transformer) + handler := crud.NewListHandler[Output, uint, *Model](logger, transformer) - qb := db_repo.NewQueryBuilder() + qb := dbRepo.NewQueryBuilder() qb.Table("footable") qb.Where("(((name = ?)))", "foobar") qb.GroupBy("id") qb.OrderBy("name", "ASC") qb.Page(0, 2) - transformer.Repo.On("GetMetadata").Return(db_repo.Metadata{ + transformer.Repo.EXPECT().GetMetadata().Return(dbRepo.Metadata{ TableName: "footable", PrimaryKey: "id", - Mappings: db_repo.FieldMappings{ - "id": db_repo.NewFieldMapping("id"), - "name": db_repo.NewFieldMapping("name"), + Mappings: dbRepo.FieldMappings{ + "id": dbRepo.NewFieldMapping("id"), + "name": dbRepo.NewFieldMapping("name"), }, }) - transformer.Repo.On("Count", mock.AnythingOfType("context.backgroundCtx"), qb, &Model{}).Return(1, nil) + + transformer.Repo.EXPECT().Count(context.Background(), qb).Return(1, nil) body := `{"filter":{"matches":[{"values":["foobar"],"dimension":"name","operator":"="}],"bool":"and"},"order":[{"field":"name","direction":"ASC"}],"page":{"offset":0,"limit":2}}` response := httpserver.HttpTest("PUT", "/:id", "/1", body, handler) assert.Equal(t, http.StatusOK, response.Code) - assert.JSONEq(t, `{"total":1,"results":[{"Id":1,"UpdatedAt":"2006-01-02T15:04:05Z","CreatedAt":"2006-01-02T15:04:05Z","name":"foobar"}]}`, response.Body.String()) + assert.JSONEq(t, `{"total":1,"results":[{"id":1,"updatedAt":"2006-01-02T15:04:05Z","createdAt":"2006-01-02T15:04:05Z","name":"foobar"}]}`, response.Body.String()) transformer.Repo.AssertExpectations(t) } diff --git a/pkg/httpserver/crud/delete.go b/pkg/httpserver/crud/delete.go index e632702cd..26261ccd3 100644 --- a/pkg/httpserver/crud/delete.go +++ b/pkg/httpserver/crud/delete.go @@ -6,19 +6,20 @@ import ( "net/http" "github.com/gin-gonic/gin" - "github.com/justtrackio/gosoline/pkg/db-repo" + dbRepo "github.com/justtrackio/gosoline/pkg/db-repo" "github.com/justtrackio/gosoline/pkg/httpserver" "github.com/justtrackio/gosoline/pkg/log" + "github.com/justtrackio/gosoline/pkg/mdl" "github.com/justtrackio/gosoline/pkg/validation" ) -type deleteHandler struct { +type deleteHandler[O any, K mdl.PossibleIdentifier, M dbRepo.ModelBased[K]] struct { logger log.Logger - transformer BaseHandler + transformer BaseHandler[O, K, M] } -func NewDeleteHandler(logger log.Logger, transformer BaseHandler) gin.HandlerFunc { - dh := deleteHandler{ +func NewDeleteHandler[O any, K mdl.PossibleIdentifier, M dbRepo.ModelBased[K]](logger log.Logger, transformer BaseHandler[O, K, M]) gin.HandlerFunc { + dh := deleteHandler[O, K, M]{ transformer: transformer, logger: logger, } @@ -26,19 +27,18 @@ func NewDeleteHandler(logger log.Logger, transformer BaseHandler) gin.HandlerFun return httpserver.CreateHandler(dh) } -func (dh deleteHandler) Handle(ctx context.Context, request *httpserver.Request) (*httpserver.Response, error) { - id, valid := httpserver.GetUintFromRequest(request, "id") +func (dh deleteHandler[O, K, M]) Handle(ctx context.Context, request *httpserver.Request) (*httpserver.Response, error) { + id, valid := httpserver.GetIdentifierFromRequest[K](request, "id") if !valid { return nil, errors.New("no valid id provided") } repo := dh.transformer.GetRepository() - model := dh.transformer.GetModel() - err := repo.Read(ctx, id, model) + model, err := repo.Read(ctx, *id) - var notFound db_repo.RecordNotFoundError + var notFound dbRepo.RecordNotFoundError if errors.As(err, ¬Found) { dh.logger.WithContext(ctx).Warn("failed to delete model: %s", err) diff --git a/pkg/httpserver/crud/handler.go b/pkg/httpserver/crud/handler.go index d0dacb722..21b2724bc 100644 --- a/pkg/httpserver/crud/handler.go +++ b/pkg/httpserver/crud/handler.go @@ -6,107 +6,94 @@ import ( "net/http" "github.com/jinzhu/inflection" - "github.com/justtrackio/gosoline/pkg/db-repo" + dbRepo "github.com/justtrackio/gosoline/pkg/db-repo" "github.com/justtrackio/gosoline/pkg/httpserver" "github.com/justtrackio/gosoline/pkg/log" + "github.com/justtrackio/gosoline/pkg/mdl" ) const DefaultApiView = "api" -//go:generate mockery --name Repository -type Repository interface { - Create(ctx context.Context, value db_repo.ModelBased) error - Read(ctx context.Context, id *uint, out db_repo.ModelBased) error - Update(ctx context.Context, value db_repo.ModelBased) error - Delete(ctx context.Context, value db_repo.ModelBased) error - Query(ctx context.Context, qb *db_repo.QueryBuilder, result interface{}) error - Count(ctx context.Context, qb *db_repo.QueryBuilder, model db_repo.ModelBased) (int, error) - GetMetadata() db_repo.Metadata -} - //go:generate mockery --name BaseHandler -type BaseHandler interface { - GetRepository() Repository - GetModel() db_repo.ModelBased - TransformOutput(ctx context.Context, model db_repo.ModelBased, apiView string) (output interface{}, err error) +type BaseHandler[O any, K mdl.PossibleIdentifier, M dbRepo.ModelBased[K]] interface { + GetRepository() dbRepo.Repository[K, M] + TransformOutput(ctx context.Context, model M, apiView string) (output O, err error) } //go:generate mockery --name BaseCreateHandler -type BaseCreateHandler interface { - GetCreateInput() interface{} - TransformCreate(ctx context.Context, input interface{}, model db_repo.ModelBased) (err error) +type BaseCreateHandler[I any, K mdl.PossibleIdentifier, M dbRepo.ModelBased[K]] interface { + TransformCreate(ctx context.Context, input *I) (M, error) } //go:generate mockery --name CreateHandler -type CreateHandler interface { - BaseHandler - BaseCreateHandler +type CreateHandler[I any, O any, K mdl.PossibleIdentifier, M dbRepo.ModelBased[K]] interface { + BaseHandler[O, K, M] + BaseCreateHandler[I, K, M] } //go:generate mockery --name BaseUpdateHandler -type BaseUpdateHandler interface { - GetUpdateInput() interface{} - TransformUpdate(ctx context.Context, input interface{}, model db_repo.ModelBased) (err error) +type BaseUpdateHandler[I any, K mdl.PossibleIdentifier, M dbRepo.ModelBased[K]] interface { + TransformUpdate(ctx context.Context, input *I, model M) (M, error) } //go:generate mockery --name UpdateHandler -type UpdateHandler interface { - BaseHandler - BaseUpdateHandler +type UpdateHandler[I any, O any, K mdl.PossibleIdentifier, M dbRepo.ModelBased[K]] interface { + BaseHandler[O, K, M] + BaseUpdateHandler[I, K, M] } //go:generate mockery --name BaseListHandler -type BaseListHandler interface { - List(ctx context.Context, qb *db_repo.QueryBuilder, apiView string) (out interface{}, err error) +type BaseListHandler[O any] interface { + List(ctx context.Context, qb *dbRepo.QueryBuilder, apiView string) (out []O, err error) } //go:generate mockery --name ListHandler -type ListHandler interface { - BaseHandler - BaseListHandler +type ListHandler[O any, K mdl.PossibleIdentifier, M dbRepo.ModelBased[K]] interface { + BaseHandler[O, K, M] + BaseListHandler[O] } //go:generate mockery --name Handler -type Handler interface { - BaseHandler - BaseCreateHandler - BaseUpdateHandler - BaseListHandler +type Handler[CI any, UI any, O any, K mdl.PossibleIdentifier, M dbRepo.ModelBased[K]] interface { + BaseHandler[O, K, M] + BaseCreateHandler[CI, K, M] + BaseUpdateHandler[UI, K, M] + BaseListHandler[O] } -func AddCrudHandlers(logger log.Logger, d *httpserver.Definitions, version int, basePath string, handler Handler) { - AddCreateHandler(logger, d, version, basePath, handler) - AddReadHandler(logger, d, version, basePath, handler) - AddUpdateHandler(logger, d, version, basePath, handler) - AddDeleteHandler(logger, d, version, basePath, handler) - AddListHandler(logger, d, version, basePath, handler) +func AddCrudHandlers[CI any, UI any, O any, K mdl.PossibleIdentifier, M dbRepo.ModelBased[K]](logger log.Logger, d *httpserver.Definitions, version int, basePath string, handler Handler[CI, UI, O, K, M]) { + AddCreateHandler[CI, O, K, M](logger, d, version, basePath, handler) + AddReadHandler[O, K, M](logger, d, version, basePath, handler) + AddUpdateHandler[UI, O, K, M](logger, d, version, basePath, handler) + AddDeleteHandler[O, K, M](logger, d, version, basePath, handler) + AddListHandler[O, K, M](logger, d, version, basePath, handler) } -func AddCreateHandler(logger log.Logger, d *httpserver.Definitions, version int, basePath string, handler CreateHandler) { +func AddCreateHandler[I any, O any, K mdl.PossibleIdentifier, M dbRepo.ModelBased[K]](logger log.Logger, d *httpserver.Definitions, version int, basePath string, handler CreateHandler[I, O, K, M]) { path, _ := getHandlerPaths(version, basePath) d.POST(path, NewCreateHandler(logger, handler)) } -func AddReadHandler(logger log.Logger, d *httpserver.Definitions, version int, basePath string, handler BaseHandler) { +func AddReadHandler[O any, K mdl.PossibleIdentifier, M dbRepo.ModelBased[K]](logger log.Logger, d *httpserver.Definitions, version int, basePath string, handler BaseHandler[O, K, M]) { _, idPath := getHandlerPaths(version, basePath) d.GET(idPath, NewReadHandler(logger, handler)) } -func AddUpdateHandler(logger log.Logger, d *httpserver.Definitions, version int, basePath string, handler UpdateHandler) { +func AddUpdateHandler[I any, O any, K mdl.PossibleIdentifier, M dbRepo.ModelBased[K]](logger log.Logger, d *httpserver.Definitions, version int, basePath string, handler UpdateHandler[I, O, K, M]) { _, idPath := getHandlerPaths(version, basePath) d.PUT(idPath, NewUpdateHandler(logger, handler)) } -func AddDeleteHandler(logger log.Logger, d *httpserver.Definitions, version int, basePath string, handler BaseHandler) { +func AddDeleteHandler[O any, K mdl.PossibleIdentifier, M dbRepo.ModelBased[K]](logger log.Logger, d *httpserver.Definitions, version int, basePath string, handler BaseHandler[O, K, M]) { _, idPath := getHandlerPaths(version, basePath) d.DELETE(idPath, NewDeleteHandler(logger, handler)) } -func AddListHandler(logger log.Logger, d *httpserver.Definitions, version int, basePath string, handler ListHandler) { +func AddListHandler[O any, K mdl.PossibleIdentifier, M dbRepo.ModelBased[K]](logger log.Logger, d *httpserver.Definitions, version int, basePath string, handler ListHandler[O, K, M]) { plural := inflection.Plural(basePath) path := fmt.Sprintf("/v%d/%s", version, plural) d.POST(path, NewListHandler(logger, handler)) diff --git a/pkg/httpserver/crud/list.go b/pkg/httpserver/crud/list.go index 0d7a7ce1d..9eb45086f 100644 --- a/pkg/httpserver/crud/list.go +++ b/pkg/httpserver/crud/list.go @@ -4,23 +4,25 @@ import ( "context" "github.com/gin-gonic/gin" + dbRepo "github.com/justtrackio/gosoline/pkg/db-repo" "github.com/justtrackio/gosoline/pkg/httpserver" "github.com/justtrackio/gosoline/pkg/httpserver/sql" "github.com/justtrackio/gosoline/pkg/log" + "github.com/justtrackio/gosoline/pkg/mdl" ) -type Output struct { - Total int `json:"total"` - Results interface{} `json:"results"` +type Output[O any] struct { + Total int `json:"total"` + Results []O `json:"results"` } -type listHandler struct { - transformer ListHandler +type listHandler[O any, K mdl.PossibleIdentifier, M dbRepo.ModelBased[K]] struct { + transformer ListHandler[O, K, M] logger log.Logger } -func NewListHandler(logger log.Logger, transformer ListHandler) gin.HandlerFunc { - lh := listHandler{ +func NewListHandler[O any, K mdl.PossibleIdentifier, M dbRepo.ModelBased[K]](logger log.Logger, transformer ListHandler[O, K, M]) gin.HandlerFunc { + lh := listHandler[O, K, M]{ transformer: transformer, logger: logger, } @@ -28,11 +30,11 @@ func NewListHandler(logger log.Logger, transformer ListHandler) gin.HandlerFunc return httpserver.CreateJsonHandler(lh) } -func (lh listHandler) GetInput() interface{} { +func (lh listHandler[O, K, M]) GetInput() interface{} { return sql.NewInput() } -func (lh listHandler) Handle(ctx context.Context, request *httpserver.Request) (*httpserver.Response, error) { +func (lh listHandler[O, K, M]) Handle(ctx context.Context, request *httpserver.Request) (*httpserver.Response, error) { inp := request.Body.(*sql.Input) repo := lh.transformer.GetRepository() @@ -50,13 +52,12 @@ func (lh listHandler) Handle(ctx context.Context, request *httpserver.Request) ( return nil, err } - model := lh.transformer.GetModel() - total, err := repo.Count(ctx, qb, model) + total, err := repo.Count(ctx, qb) if err != nil { return nil, err } - out := Output{ + out := Output[O]{ Total: total, Results: results, } @@ -66,3 +67,20 @@ func (lh listHandler) Handle(ctx context.Context, request *httpserver.Request) ( return resp, nil } + +func DefaultList[O any, K mdl.PossibleIdentifier, M dbRepo.ModelBased[K]](h BaseHandler[O, K, M], ctx context.Context, qb *dbRepo.QueryBuilder, apiView string) ([]O, error) { + result, err := h.GetRepository().Query(ctx, qb) + if err != nil { + return nil, err + } + + out := make([]O, len(result)) + for i, res := range result { + out[i], err = h.TransformOutput(ctx, res, apiView) + if err != nil { + return nil, err + } + } + + return out, nil +} diff --git a/pkg/httpserver/crud/mocks/BaseCreateHandler.go b/pkg/httpserver/crud/mocks/BaseCreateHandler.go index 6fed439aa..4c3075387 100644 --- a/pkg/httpserver/crud/mocks/BaseCreateHandler.go +++ b/pkg/httpserver/crud/mocks/BaseCreateHandler.go @@ -7,105 +7,73 @@ import ( db_repo "github.com/justtrackio/gosoline/pkg/db-repo" + mdl "github.com/justtrackio/gosoline/pkg/mdl" + mock "github.com/stretchr/testify/mock" ) // BaseCreateHandler is an autogenerated mock type for the BaseCreateHandler type -type BaseCreateHandler struct { +type BaseCreateHandler[I interface{}, K mdl.PossibleIdentifier, M db_repo.ModelBased[K]] struct { mock.Mock } -type BaseCreateHandler_Expecter struct { +type BaseCreateHandler_Expecter[I interface{}, K mdl.PossibleIdentifier, M db_repo.ModelBased[K]] struct { mock *mock.Mock } -func (_m *BaseCreateHandler) EXPECT() *BaseCreateHandler_Expecter { - return &BaseCreateHandler_Expecter{mock: &_m.Mock} +func (_m *BaseCreateHandler[I, K, M]) EXPECT() *BaseCreateHandler_Expecter[I, K, M] { + return &BaseCreateHandler_Expecter[I, K, M]{mock: &_m.Mock} } -// GetCreateInput provides a mock function with given fields: -func (_m *BaseCreateHandler) GetCreateInput() interface{} { - ret := _m.Called() +// TransformCreate provides a mock function with given fields: ctx, input +func (_m *BaseCreateHandler[I, K, M]) TransformCreate(ctx context.Context, input *I) (M, error) { + ret := _m.Called(ctx, input) - var r0 interface{} - if rf, ok := ret.Get(0).(func() interface{}); ok { - r0 = rf() + var r0 M + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *I) (M, error)); ok { + return rf(ctx, input) + } + if rf, ok := ret.Get(0).(func(context.Context, *I) M); ok { + r0 = rf(ctx, input) } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(interface{}) - } + r0 = ret.Get(0).(M) } - return r0 -} - -// BaseCreateHandler_GetCreateInput_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetCreateInput' -type BaseCreateHandler_GetCreateInput_Call struct { - *mock.Call -} - -// GetCreateInput is a helper method to define mock.On call -func (_e *BaseCreateHandler_Expecter) GetCreateInput() *BaseCreateHandler_GetCreateInput_Call { - return &BaseCreateHandler_GetCreateInput_Call{Call: _e.mock.On("GetCreateInput")} -} - -func (_c *BaseCreateHandler_GetCreateInput_Call) Run(run func()) *BaseCreateHandler_GetCreateInput_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *BaseCreateHandler_GetCreateInput_Call) Return(_a0 interface{}) *BaseCreateHandler_GetCreateInput_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *BaseCreateHandler_GetCreateInput_Call) RunAndReturn(run func() interface{}) *BaseCreateHandler_GetCreateInput_Call { - _c.Call.Return(run) - return _c -} - -// TransformCreate provides a mock function with given fields: ctx, input, model -func (_m *BaseCreateHandler) TransformCreate(ctx context.Context, input interface{}, model db_repo.ModelBased) error { - ret := _m.Called(ctx, input, model) - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, interface{}, db_repo.ModelBased) error); ok { - r0 = rf(ctx, input, model) + if rf, ok := ret.Get(1).(func(context.Context, *I) error); ok { + r1 = rf(ctx, input) } else { - r0 = ret.Error(0) + r1 = ret.Error(1) } - return r0 + return r0, r1 } // BaseCreateHandler_TransformCreate_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'TransformCreate' -type BaseCreateHandler_TransformCreate_Call struct { +type BaseCreateHandler_TransformCreate_Call[I interface{}, K mdl.PossibleIdentifier, M db_repo.ModelBased[K]] struct { *mock.Call } // TransformCreate is a helper method to define mock.On call // - ctx context.Context -// - input interface{} -// - model db_repo.ModelBased -func (_e *BaseCreateHandler_Expecter) TransformCreate(ctx interface{}, input interface{}, model interface{}) *BaseCreateHandler_TransformCreate_Call { - return &BaseCreateHandler_TransformCreate_Call{Call: _e.mock.On("TransformCreate", ctx, input, model)} +// - input *I +func (_e *BaseCreateHandler_Expecter[I, K, M]) TransformCreate(ctx interface{}, input interface{}) *BaseCreateHandler_TransformCreate_Call[I, K, M] { + return &BaseCreateHandler_TransformCreate_Call[I, K, M]{Call: _e.mock.On("TransformCreate", ctx, input)} } -func (_c *BaseCreateHandler_TransformCreate_Call) Run(run func(ctx context.Context, input interface{}, model db_repo.ModelBased)) *BaseCreateHandler_TransformCreate_Call { +func (_c *BaseCreateHandler_TransformCreate_Call[I, K, M]) Run(run func(ctx context.Context, input *I)) *BaseCreateHandler_TransformCreate_Call[I, K, M] { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(interface{}), args[2].(db_repo.ModelBased)) + run(args[0].(context.Context), args[1].(*I)) }) return _c } -func (_c *BaseCreateHandler_TransformCreate_Call) Return(err error) *BaseCreateHandler_TransformCreate_Call { - _c.Call.Return(err) +func (_c *BaseCreateHandler_TransformCreate_Call[I, K, M]) Return(_a0 M, _a1 error) *BaseCreateHandler_TransformCreate_Call[I, K, M] { + _c.Call.Return(_a0, _a1) return _c } -func (_c *BaseCreateHandler_TransformCreate_Call) RunAndReturn(run func(context.Context, interface{}, db_repo.ModelBased) error) *BaseCreateHandler_TransformCreate_Call { +func (_c *BaseCreateHandler_TransformCreate_Call[I, K, M]) RunAndReturn(run func(context.Context, *I) (M, error)) *BaseCreateHandler_TransformCreate_Call[I, K, M] { _c.Call.Return(run) return _c } @@ -116,8 +84,8 @@ type mockConstructorTestingTNewBaseCreateHandler interface { } // NewBaseCreateHandler creates a new instance of BaseCreateHandler. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewBaseCreateHandler(t mockConstructorTestingTNewBaseCreateHandler) *BaseCreateHandler { - mock := &BaseCreateHandler{} +func NewBaseCreateHandler[I interface{}, K mdl.PossibleIdentifier, M db_repo.ModelBased[K]](t mockConstructorTestingTNewBaseCreateHandler) *BaseCreateHandler[I, K, M] { + mock := &BaseCreateHandler[I, K, M]{} mock.Mock.Test(t) t.Cleanup(func() { mock.AssertExpectations(t) }) diff --git a/pkg/httpserver/crud/mocks/BaseHandler.go b/pkg/httpserver/crud/mocks/BaseHandler.go index b537a2d32..b8198c9b2 100644 --- a/pkg/httpserver/crud/mocks/BaseHandler.go +++ b/pkg/httpserver/crud/mocks/BaseHandler.go @@ -6,77 +6,35 @@ import ( context "context" db_repo "github.com/justtrackio/gosoline/pkg/db-repo" - crud "github.com/justtrackio/gosoline/pkg/httpserver/crud" + + mdl "github.com/justtrackio/gosoline/pkg/mdl" mock "github.com/stretchr/testify/mock" ) // BaseHandler is an autogenerated mock type for the BaseHandler type -type BaseHandler struct { +type BaseHandler[O interface{}, K mdl.PossibleIdentifier, M db_repo.ModelBased[K]] struct { mock.Mock } -type BaseHandler_Expecter struct { +type BaseHandler_Expecter[O interface{}, K mdl.PossibleIdentifier, M db_repo.ModelBased[K]] struct { mock *mock.Mock } -func (_m *BaseHandler) EXPECT() *BaseHandler_Expecter { - return &BaseHandler_Expecter{mock: &_m.Mock} -} - -// GetModel provides a mock function with given fields: -func (_m *BaseHandler) GetModel() db_repo.ModelBased { - ret := _m.Called() - - var r0 db_repo.ModelBased - if rf, ok := ret.Get(0).(func() db_repo.ModelBased); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(db_repo.ModelBased) - } - } - - return r0 -} - -// BaseHandler_GetModel_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetModel' -type BaseHandler_GetModel_Call struct { - *mock.Call -} - -// GetModel is a helper method to define mock.On call -func (_e *BaseHandler_Expecter) GetModel() *BaseHandler_GetModel_Call { - return &BaseHandler_GetModel_Call{Call: _e.mock.On("GetModel")} -} - -func (_c *BaseHandler_GetModel_Call) Run(run func()) *BaseHandler_GetModel_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *BaseHandler_GetModel_Call) Return(_a0 db_repo.ModelBased) *BaseHandler_GetModel_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *BaseHandler_GetModel_Call) RunAndReturn(run func() db_repo.ModelBased) *BaseHandler_GetModel_Call { - _c.Call.Return(run) - return _c +func (_m *BaseHandler[O, K, M]) EXPECT() *BaseHandler_Expecter[O, K, M] { + return &BaseHandler_Expecter[O, K, M]{mock: &_m.Mock} } // GetRepository provides a mock function with given fields: -func (_m *BaseHandler) GetRepository() crud.Repository { +func (_m *BaseHandler[O, K, M]) GetRepository() db_repo.Repository[K, M] { ret := _m.Called() - var r0 crud.Repository - if rf, ok := ret.Get(0).(func() crud.Repository); ok { + var r0 db_repo.Repository[K, M] + if rf, ok := ret.Get(0).(func() db_repo.Repository[K, M]); ok { r0 = rf() } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(crud.Repository) + r0 = ret.Get(0).(db_repo.Repository[K, M]) } } @@ -84,50 +42,48 @@ func (_m *BaseHandler) GetRepository() crud.Repository { } // BaseHandler_GetRepository_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetRepository' -type BaseHandler_GetRepository_Call struct { +type BaseHandler_GetRepository_Call[O interface{}, K mdl.PossibleIdentifier, M db_repo.ModelBased[K]] struct { *mock.Call } // GetRepository is a helper method to define mock.On call -func (_e *BaseHandler_Expecter) GetRepository() *BaseHandler_GetRepository_Call { - return &BaseHandler_GetRepository_Call{Call: _e.mock.On("GetRepository")} +func (_e *BaseHandler_Expecter[O, K, M]) GetRepository() *BaseHandler_GetRepository_Call[O, K, M] { + return &BaseHandler_GetRepository_Call[O, K, M]{Call: _e.mock.On("GetRepository")} } -func (_c *BaseHandler_GetRepository_Call) Run(run func()) *BaseHandler_GetRepository_Call { +func (_c *BaseHandler_GetRepository_Call[O, K, M]) Run(run func()) *BaseHandler_GetRepository_Call[O, K, M] { _c.Call.Run(func(args mock.Arguments) { run() }) return _c } -func (_c *BaseHandler_GetRepository_Call) Return(_a0 crud.Repository) *BaseHandler_GetRepository_Call { +func (_c *BaseHandler_GetRepository_Call[O, K, M]) Return(_a0 db_repo.Repository[K, M]) *BaseHandler_GetRepository_Call[O, K, M] { _c.Call.Return(_a0) return _c } -func (_c *BaseHandler_GetRepository_Call) RunAndReturn(run func() crud.Repository) *BaseHandler_GetRepository_Call { +func (_c *BaseHandler_GetRepository_Call[O, K, M]) RunAndReturn(run func() db_repo.Repository[K, M]) *BaseHandler_GetRepository_Call[O, K, M] { _c.Call.Return(run) return _c } // TransformOutput provides a mock function with given fields: ctx, model, apiView -func (_m *BaseHandler) TransformOutput(ctx context.Context, model db_repo.ModelBased, apiView string) (interface{}, error) { +func (_m *BaseHandler[O, K, M]) TransformOutput(ctx context.Context, model M, apiView string) (O, error) { ret := _m.Called(ctx, model, apiView) - var r0 interface{} + var r0 O var r1 error - if rf, ok := ret.Get(0).(func(context.Context, db_repo.ModelBased, string) (interface{}, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, M, string) (O, error)); ok { return rf(ctx, model, apiView) } - if rf, ok := ret.Get(0).(func(context.Context, db_repo.ModelBased, string) interface{}); ok { + if rf, ok := ret.Get(0).(func(context.Context, M, string) O); ok { r0 = rf(ctx, model, apiView) } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(interface{}) - } + r0 = ret.Get(0).(O) } - if rf, ok := ret.Get(1).(func(context.Context, db_repo.ModelBased, string) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, M, string) error); ok { r1 = rf(ctx, model, apiView) } else { r1 = ret.Error(1) @@ -137,31 +93,31 @@ func (_m *BaseHandler) TransformOutput(ctx context.Context, model db_repo.ModelB } // BaseHandler_TransformOutput_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'TransformOutput' -type BaseHandler_TransformOutput_Call struct { +type BaseHandler_TransformOutput_Call[O interface{}, K mdl.PossibleIdentifier, M db_repo.ModelBased[K]] struct { *mock.Call } // TransformOutput is a helper method to define mock.On call // - ctx context.Context -// - model db_repo.ModelBased +// - model M // - apiView string -func (_e *BaseHandler_Expecter) TransformOutput(ctx interface{}, model interface{}, apiView interface{}) *BaseHandler_TransformOutput_Call { - return &BaseHandler_TransformOutput_Call{Call: _e.mock.On("TransformOutput", ctx, model, apiView)} +func (_e *BaseHandler_Expecter[O, K, M]) TransformOutput(ctx interface{}, model interface{}, apiView interface{}) *BaseHandler_TransformOutput_Call[O, K, M] { + return &BaseHandler_TransformOutput_Call[O, K, M]{Call: _e.mock.On("TransformOutput", ctx, model, apiView)} } -func (_c *BaseHandler_TransformOutput_Call) Run(run func(ctx context.Context, model db_repo.ModelBased, apiView string)) *BaseHandler_TransformOutput_Call { +func (_c *BaseHandler_TransformOutput_Call[O, K, M]) Run(run func(ctx context.Context, model M, apiView string)) *BaseHandler_TransformOutput_Call[O, K, M] { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(db_repo.ModelBased), args[2].(string)) + run(args[0].(context.Context), args[1].(M), args[2].(string)) }) return _c } -func (_c *BaseHandler_TransformOutput_Call) Return(output interface{}, err error) *BaseHandler_TransformOutput_Call { +func (_c *BaseHandler_TransformOutput_Call[O, K, M]) Return(output O, err error) *BaseHandler_TransformOutput_Call[O, K, M] { _c.Call.Return(output, err) return _c } -func (_c *BaseHandler_TransformOutput_Call) RunAndReturn(run func(context.Context, db_repo.ModelBased, string) (interface{}, error)) *BaseHandler_TransformOutput_Call { +func (_c *BaseHandler_TransformOutput_Call[O, K, M]) RunAndReturn(run func(context.Context, M, string) (O, error)) *BaseHandler_TransformOutput_Call[O, K, M] { _c.Call.Return(run) return _c } @@ -172,8 +128,8 @@ type mockConstructorTestingTNewBaseHandler interface { } // NewBaseHandler creates a new instance of BaseHandler. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewBaseHandler(t mockConstructorTestingTNewBaseHandler) *BaseHandler { - mock := &BaseHandler{} +func NewBaseHandler[O interface{}, K mdl.PossibleIdentifier, M db_repo.ModelBased[K]](t mockConstructorTestingTNewBaseHandler) *BaseHandler[O, K, M] { + mock := &BaseHandler[O, K, M]{} mock.Mock.Test(t) t.Cleanup(func() { mock.AssertExpectations(t) }) diff --git a/pkg/httpserver/crud/mocks/BaseListHandler.go b/pkg/httpserver/crud/mocks/BaseListHandler.go index cf0866f3f..a637507e9 100644 --- a/pkg/httpserver/crud/mocks/BaseListHandler.go +++ b/pkg/httpserver/crud/mocks/BaseListHandler.go @@ -11,32 +11,32 @@ import ( ) // BaseListHandler is an autogenerated mock type for the BaseListHandler type -type BaseListHandler struct { +type BaseListHandler[O interface{}] struct { mock.Mock } -type BaseListHandler_Expecter struct { +type BaseListHandler_Expecter[O interface{}] struct { mock *mock.Mock } -func (_m *BaseListHandler) EXPECT() *BaseListHandler_Expecter { - return &BaseListHandler_Expecter{mock: &_m.Mock} +func (_m *BaseListHandler[O]) EXPECT() *BaseListHandler_Expecter[O] { + return &BaseListHandler_Expecter[O]{mock: &_m.Mock} } // List provides a mock function with given fields: ctx, qb, apiView -func (_m *BaseListHandler) List(ctx context.Context, qb *db_repo.QueryBuilder, apiView string) (interface{}, error) { +func (_m *BaseListHandler[O]) List(ctx context.Context, qb *db_repo.QueryBuilder, apiView string) ([]O, error) { ret := _m.Called(ctx, qb, apiView) - var r0 interface{} + var r0 []O var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *db_repo.QueryBuilder, string) (interface{}, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, *db_repo.QueryBuilder, string) ([]O, error)); ok { return rf(ctx, qb, apiView) } - if rf, ok := ret.Get(0).(func(context.Context, *db_repo.QueryBuilder, string) interface{}); ok { + if rf, ok := ret.Get(0).(func(context.Context, *db_repo.QueryBuilder, string) []O); ok { r0 = rf(ctx, qb, apiView) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(interface{}) + r0 = ret.Get(0).([]O) } } @@ -50,7 +50,7 @@ func (_m *BaseListHandler) List(ctx context.Context, qb *db_repo.QueryBuilder, a } // BaseListHandler_List_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'List' -type BaseListHandler_List_Call struct { +type BaseListHandler_List_Call[O interface{}] struct { *mock.Call } @@ -58,23 +58,23 @@ type BaseListHandler_List_Call struct { // - ctx context.Context // - qb *db_repo.QueryBuilder // - apiView string -func (_e *BaseListHandler_Expecter) List(ctx interface{}, qb interface{}, apiView interface{}) *BaseListHandler_List_Call { - return &BaseListHandler_List_Call{Call: _e.mock.On("List", ctx, qb, apiView)} +func (_e *BaseListHandler_Expecter[O]) List(ctx interface{}, qb interface{}, apiView interface{}) *BaseListHandler_List_Call[O] { + return &BaseListHandler_List_Call[O]{Call: _e.mock.On("List", ctx, qb, apiView)} } -func (_c *BaseListHandler_List_Call) Run(run func(ctx context.Context, qb *db_repo.QueryBuilder, apiView string)) *BaseListHandler_List_Call { +func (_c *BaseListHandler_List_Call[O]) Run(run func(ctx context.Context, qb *db_repo.QueryBuilder, apiView string)) *BaseListHandler_List_Call[O] { _c.Call.Run(func(args mock.Arguments) { run(args[0].(context.Context), args[1].(*db_repo.QueryBuilder), args[2].(string)) }) return _c } -func (_c *BaseListHandler_List_Call) Return(out interface{}, err error) *BaseListHandler_List_Call { +func (_c *BaseListHandler_List_Call[O]) Return(out []O, err error) *BaseListHandler_List_Call[O] { _c.Call.Return(out, err) return _c } -func (_c *BaseListHandler_List_Call) RunAndReturn(run func(context.Context, *db_repo.QueryBuilder, string) (interface{}, error)) *BaseListHandler_List_Call { +func (_c *BaseListHandler_List_Call[O]) RunAndReturn(run func(context.Context, *db_repo.QueryBuilder, string) ([]O, error)) *BaseListHandler_List_Call[O] { _c.Call.Return(run) return _c } @@ -85,8 +85,8 @@ type mockConstructorTestingTNewBaseListHandler interface { } // NewBaseListHandler creates a new instance of BaseListHandler. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewBaseListHandler(t mockConstructorTestingTNewBaseListHandler) *BaseListHandler { - mock := &BaseListHandler{} +func NewBaseListHandler[O interface{}](t mockConstructorTestingTNewBaseListHandler) *BaseListHandler[O] { + mock := &BaseListHandler[O]{} mock.Mock.Test(t) t.Cleanup(func() { mock.AssertExpectations(t) }) diff --git a/pkg/httpserver/crud/mocks/BaseUpdateHandler.go b/pkg/httpserver/crud/mocks/BaseUpdateHandler.go index ebbf971ab..93e06e084 100644 --- a/pkg/httpserver/crud/mocks/BaseUpdateHandler.go +++ b/pkg/httpserver/crud/mocks/BaseUpdateHandler.go @@ -7,105 +7,74 @@ import ( db_repo "github.com/justtrackio/gosoline/pkg/db-repo" + mdl "github.com/justtrackio/gosoline/pkg/mdl" + mock "github.com/stretchr/testify/mock" ) // BaseUpdateHandler is an autogenerated mock type for the BaseUpdateHandler type -type BaseUpdateHandler struct { +type BaseUpdateHandler[I interface{}, K mdl.PossibleIdentifier, M db_repo.ModelBased[K]] struct { mock.Mock } -type BaseUpdateHandler_Expecter struct { +type BaseUpdateHandler_Expecter[I interface{}, K mdl.PossibleIdentifier, M db_repo.ModelBased[K]] struct { mock *mock.Mock } -func (_m *BaseUpdateHandler) EXPECT() *BaseUpdateHandler_Expecter { - return &BaseUpdateHandler_Expecter{mock: &_m.Mock} -} - -// GetUpdateInput provides a mock function with given fields: -func (_m *BaseUpdateHandler) GetUpdateInput() interface{} { - ret := _m.Called() - - var r0 interface{} - if rf, ok := ret.Get(0).(func() interface{}); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(interface{}) - } - } - - return r0 -} - -// BaseUpdateHandler_GetUpdateInput_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetUpdateInput' -type BaseUpdateHandler_GetUpdateInput_Call struct { - *mock.Call -} - -// GetUpdateInput is a helper method to define mock.On call -func (_e *BaseUpdateHandler_Expecter) GetUpdateInput() *BaseUpdateHandler_GetUpdateInput_Call { - return &BaseUpdateHandler_GetUpdateInput_Call{Call: _e.mock.On("GetUpdateInput")} -} - -func (_c *BaseUpdateHandler_GetUpdateInput_Call) Run(run func()) *BaseUpdateHandler_GetUpdateInput_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *BaseUpdateHandler_GetUpdateInput_Call) Return(_a0 interface{}) *BaseUpdateHandler_GetUpdateInput_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *BaseUpdateHandler_GetUpdateInput_Call) RunAndReturn(run func() interface{}) *BaseUpdateHandler_GetUpdateInput_Call { - _c.Call.Return(run) - return _c +func (_m *BaseUpdateHandler[I, K, M]) EXPECT() *BaseUpdateHandler_Expecter[I, K, M] { + return &BaseUpdateHandler_Expecter[I, K, M]{mock: &_m.Mock} } // TransformUpdate provides a mock function with given fields: ctx, input, model -func (_m *BaseUpdateHandler) TransformUpdate(ctx context.Context, input interface{}, model db_repo.ModelBased) error { +func (_m *BaseUpdateHandler[I, K, M]) TransformUpdate(ctx context.Context, input *I, model M) (M, error) { ret := _m.Called(ctx, input, model) - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, interface{}, db_repo.ModelBased) error); ok { + var r0 M + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *I, M) (M, error)); ok { + return rf(ctx, input, model) + } + if rf, ok := ret.Get(0).(func(context.Context, *I, M) M); ok { r0 = rf(ctx, input, model) } else { - r0 = ret.Error(0) + r0 = ret.Get(0).(M) + } + + if rf, ok := ret.Get(1).(func(context.Context, *I, M) error); ok { + r1 = rf(ctx, input, model) + } else { + r1 = ret.Error(1) } - return r0 + return r0, r1 } // BaseUpdateHandler_TransformUpdate_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'TransformUpdate' -type BaseUpdateHandler_TransformUpdate_Call struct { +type BaseUpdateHandler_TransformUpdate_Call[I interface{}, K mdl.PossibleIdentifier, M db_repo.ModelBased[K]] struct { *mock.Call } // TransformUpdate is a helper method to define mock.On call // - ctx context.Context -// - input interface{} -// - model db_repo.ModelBased -func (_e *BaseUpdateHandler_Expecter) TransformUpdate(ctx interface{}, input interface{}, model interface{}) *BaseUpdateHandler_TransformUpdate_Call { - return &BaseUpdateHandler_TransformUpdate_Call{Call: _e.mock.On("TransformUpdate", ctx, input, model)} +// - input *I +// - model M +func (_e *BaseUpdateHandler_Expecter[I, K, M]) TransformUpdate(ctx interface{}, input interface{}, model interface{}) *BaseUpdateHandler_TransformUpdate_Call[I, K, M] { + return &BaseUpdateHandler_TransformUpdate_Call[I, K, M]{Call: _e.mock.On("TransformUpdate", ctx, input, model)} } -func (_c *BaseUpdateHandler_TransformUpdate_Call) Run(run func(ctx context.Context, input interface{}, model db_repo.ModelBased)) *BaseUpdateHandler_TransformUpdate_Call { +func (_c *BaseUpdateHandler_TransformUpdate_Call[I, K, M]) Run(run func(ctx context.Context, input *I, model M)) *BaseUpdateHandler_TransformUpdate_Call[I, K, M] { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(interface{}), args[2].(db_repo.ModelBased)) + run(args[0].(context.Context), args[1].(*I), args[2].(M)) }) return _c } -func (_c *BaseUpdateHandler_TransformUpdate_Call) Return(err error) *BaseUpdateHandler_TransformUpdate_Call { - _c.Call.Return(err) +func (_c *BaseUpdateHandler_TransformUpdate_Call[I, K, M]) Return(_a0 M, _a1 error) *BaseUpdateHandler_TransformUpdate_Call[I, K, M] { + _c.Call.Return(_a0, _a1) return _c } -func (_c *BaseUpdateHandler_TransformUpdate_Call) RunAndReturn(run func(context.Context, interface{}, db_repo.ModelBased) error) *BaseUpdateHandler_TransformUpdate_Call { +func (_c *BaseUpdateHandler_TransformUpdate_Call[I, K, M]) RunAndReturn(run func(context.Context, *I, M) (M, error)) *BaseUpdateHandler_TransformUpdate_Call[I, K, M] { _c.Call.Return(run) return _c } @@ -116,8 +85,8 @@ type mockConstructorTestingTNewBaseUpdateHandler interface { } // NewBaseUpdateHandler creates a new instance of BaseUpdateHandler. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewBaseUpdateHandler(t mockConstructorTestingTNewBaseUpdateHandler) *BaseUpdateHandler { - mock := &BaseUpdateHandler{} +func NewBaseUpdateHandler[I interface{}, K mdl.PossibleIdentifier, M db_repo.ModelBased[K]](t mockConstructorTestingTNewBaseUpdateHandler) *BaseUpdateHandler[I, K, M] { + mock := &BaseUpdateHandler[I, K, M]{} mock.Mock.Test(t) t.Cleanup(func() { mock.AssertExpectations(t) }) diff --git a/pkg/httpserver/crud/mocks/CreateHandler.go b/pkg/httpserver/crud/mocks/CreateHandler.go index 2c2eab830..cfc28fa2e 100644 --- a/pkg/httpserver/crud/mocks/CreateHandler.go +++ b/pkg/httpserver/crud/mocks/CreateHandler.go @@ -6,215 +6,137 @@ import ( context "context" db_repo "github.com/justtrackio/gosoline/pkg/db-repo" - crud "github.com/justtrackio/gosoline/pkg/httpserver/crud" + + mdl "github.com/justtrackio/gosoline/pkg/mdl" mock "github.com/stretchr/testify/mock" ) // CreateHandler is an autogenerated mock type for the CreateHandler type -type CreateHandler struct { +type CreateHandler[I interface{}, O interface{}, K mdl.PossibleIdentifier, M db_repo.ModelBased[K]] struct { mock.Mock } -type CreateHandler_Expecter struct { +type CreateHandler_Expecter[I interface{}, O interface{}, K mdl.PossibleIdentifier, M db_repo.ModelBased[K]] struct { mock *mock.Mock } -func (_m *CreateHandler) EXPECT() *CreateHandler_Expecter { - return &CreateHandler_Expecter{mock: &_m.Mock} +func (_m *CreateHandler[I, O, K, M]) EXPECT() *CreateHandler_Expecter[I, O, K, M] { + return &CreateHandler_Expecter[I, O, K, M]{mock: &_m.Mock} } -// GetCreateInput provides a mock function with given fields: -func (_m *CreateHandler) GetCreateInput() interface{} { +// GetRepository provides a mock function with given fields: +func (_m *CreateHandler[I, O, K, M]) GetRepository() db_repo.Repository[K, M] { ret := _m.Called() - var r0 interface{} - if rf, ok := ret.Get(0).(func() interface{}); ok { + var r0 db_repo.Repository[K, M] + if rf, ok := ret.Get(0).(func() db_repo.Repository[K, M]); ok { r0 = rf() } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(interface{}) + r0 = ret.Get(0).(db_repo.Repository[K, M]) } } return r0 } -// CreateHandler_GetCreateInput_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetCreateInput' -type CreateHandler_GetCreateInput_Call struct { +// CreateHandler_GetRepository_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetRepository' +type CreateHandler_GetRepository_Call[I interface{}, O interface{}, K mdl.PossibleIdentifier, M db_repo.ModelBased[K]] struct { *mock.Call } -// GetCreateInput is a helper method to define mock.On call -func (_e *CreateHandler_Expecter) GetCreateInput() *CreateHandler_GetCreateInput_Call { - return &CreateHandler_GetCreateInput_Call{Call: _e.mock.On("GetCreateInput")} +// GetRepository is a helper method to define mock.On call +func (_e *CreateHandler_Expecter[I, O, K, M]) GetRepository() *CreateHandler_GetRepository_Call[I, O, K, M] { + return &CreateHandler_GetRepository_Call[I, O, K, M]{Call: _e.mock.On("GetRepository")} } -func (_c *CreateHandler_GetCreateInput_Call) Run(run func()) *CreateHandler_GetCreateInput_Call { +func (_c *CreateHandler_GetRepository_Call[I, O, K, M]) Run(run func()) *CreateHandler_GetRepository_Call[I, O, K, M] { _c.Call.Run(func(args mock.Arguments) { run() }) return _c } -func (_c *CreateHandler_GetCreateInput_Call) Return(_a0 interface{}) *CreateHandler_GetCreateInput_Call { +func (_c *CreateHandler_GetRepository_Call[I, O, K, M]) Return(_a0 db_repo.Repository[K, M]) *CreateHandler_GetRepository_Call[I, O, K, M] { _c.Call.Return(_a0) return _c } -func (_c *CreateHandler_GetCreateInput_Call) RunAndReturn(run func() interface{}) *CreateHandler_GetCreateInput_Call { +func (_c *CreateHandler_GetRepository_Call[I, O, K, M]) RunAndReturn(run func() db_repo.Repository[K, M]) *CreateHandler_GetRepository_Call[I, O, K, M] { _c.Call.Return(run) return _c } -// GetModel provides a mock function with given fields: -func (_m *CreateHandler) GetModel() db_repo.ModelBased { - ret := _m.Called() +// TransformCreate provides a mock function with given fields: ctx, input +func (_m *CreateHandler[I, O, K, M]) TransformCreate(ctx context.Context, input *I) (M, error) { + ret := _m.Called(ctx, input) - var r0 db_repo.ModelBased - if rf, ok := ret.Get(0).(func() db_repo.ModelBased); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(db_repo.ModelBased) - } + var r0 M + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *I) (M, error)); ok { + return rf(ctx, input) } - - return r0 -} - -// CreateHandler_GetModel_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetModel' -type CreateHandler_GetModel_Call struct { - *mock.Call -} - -// GetModel is a helper method to define mock.On call -func (_e *CreateHandler_Expecter) GetModel() *CreateHandler_GetModel_Call { - return &CreateHandler_GetModel_Call{Call: _e.mock.On("GetModel")} -} - -func (_c *CreateHandler_GetModel_Call) Run(run func()) *CreateHandler_GetModel_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *CreateHandler_GetModel_Call) Return(_a0 db_repo.ModelBased) *CreateHandler_GetModel_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *CreateHandler_GetModel_Call) RunAndReturn(run func() db_repo.ModelBased) *CreateHandler_GetModel_Call { - _c.Call.Return(run) - return _c -} - -// GetRepository provides a mock function with given fields: -func (_m *CreateHandler) GetRepository() crud.Repository { - ret := _m.Called() - - var r0 crud.Repository - if rf, ok := ret.Get(0).(func() crud.Repository); ok { - r0 = rf() + if rf, ok := ret.Get(0).(func(context.Context, *I) M); ok { + r0 = rf(ctx, input) } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(crud.Repository) - } + r0 = ret.Get(0).(M) } - return r0 -} - -// CreateHandler_GetRepository_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetRepository' -type CreateHandler_GetRepository_Call struct { - *mock.Call -} - -// GetRepository is a helper method to define mock.On call -func (_e *CreateHandler_Expecter) GetRepository() *CreateHandler_GetRepository_Call { - return &CreateHandler_GetRepository_Call{Call: _e.mock.On("GetRepository")} -} - -func (_c *CreateHandler_GetRepository_Call) Run(run func()) *CreateHandler_GetRepository_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *CreateHandler_GetRepository_Call) Return(_a0 crud.Repository) *CreateHandler_GetRepository_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *CreateHandler_GetRepository_Call) RunAndReturn(run func() crud.Repository) *CreateHandler_GetRepository_Call { - _c.Call.Return(run) - return _c -} - -// TransformCreate provides a mock function with given fields: ctx, input, model -func (_m *CreateHandler) TransformCreate(ctx context.Context, input interface{}, model db_repo.ModelBased) error { - ret := _m.Called(ctx, input, model) - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, interface{}, db_repo.ModelBased) error); ok { - r0 = rf(ctx, input, model) + if rf, ok := ret.Get(1).(func(context.Context, *I) error); ok { + r1 = rf(ctx, input) } else { - r0 = ret.Error(0) + r1 = ret.Error(1) } - return r0 + return r0, r1 } // CreateHandler_TransformCreate_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'TransformCreate' -type CreateHandler_TransformCreate_Call struct { +type CreateHandler_TransformCreate_Call[I interface{}, O interface{}, K mdl.PossibleIdentifier, M db_repo.ModelBased[K]] struct { *mock.Call } // TransformCreate is a helper method to define mock.On call // - ctx context.Context -// - input interface{} -// - model db_repo.ModelBased -func (_e *CreateHandler_Expecter) TransformCreate(ctx interface{}, input interface{}, model interface{}) *CreateHandler_TransformCreate_Call { - return &CreateHandler_TransformCreate_Call{Call: _e.mock.On("TransformCreate", ctx, input, model)} +// - input *I +func (_e *CreateHandler_Expecter[I, O, K, M]) TransformCreate(ctx interface{}, input interface{}) *CreateHandler_TransformCreate_Call[I, O, K, M] { + return &CreateHandler_TransformCreate_Call[I, O, K, M]{Call: _e.mock.On("TransformCreate", ctx, input)} } -func (_c *CreateHandler_TransformCreate_Call) Run(run func(ctx context.Context, input interface{}, model db_repo.ModelBased)) *CreateHandler_TransformCreate_Call { +func (_c *CreateHandler_TransformCreate_Call[I, O, K, M]) Run(run func(ctx context.Context, input *I)) *CreateHandler_TransformCreate_Call[I, O, K, M] { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(interface{}), args[2].(db_repo.ModelBased)) + run(args[0].(context.Context), args[1].(*I)) }) return _c } -func (_c *CreateHandler_TransformCreate_Call) Return(err error) *CreateHandler_TransformCreate_Call { - _c.Call.Return(err) +func (_c *CreateHandler_TransformCreate_Call[I, O, K, M]) Return(_a0 M, _a1 error) *CreateHandler_TransformCreate_Call[I, O, K, M] { + _c.Call.Return(_a0, _a1) return _c } -func (_c *CreateHandler_TransformCreate_Call) RunAndReturn(run func(context.Context, interface{}, db_repo.ModelBased) error) *CreateHandler_TransformCreate_Call { +func (_c *CreateHandler_TransformCreate_Call[I, O, K, M]) RunAndReturn(run func(context.Context, *I) (M, error)) *CreateHandler_TransformCreate_Call[I, O, K, M] { _c.Call.Return(run) return _c } // TransformOutput provides a mock function with given fields: ctx, model, apiView -func (_m *CreateHandler) TransformOutput(ctx context.Context, model db_repo.ModelBased, apiView string) (interface{}, error) { +func (_m *CreateHandler[I, O, K, M]) TransformOutput(ctx context.Context, model M, apiView string) (O, error) { ret := _m.Called(ctx, model, apiView) - var r0 interface{} + var r0 O var r1 error - if rf, ok := ret.Get(0).(func(context.Context, db_repo.ModelBased, string) (interface{}, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, M, string) (O, error)); ok { return rf(ctx, model, apiView) } - if rf, ok := ret.Get(0).(func(context.Context, db_repo.ModelBased, string) interface{}); ok { + if rf, ok := ret.Get(0).(func(context.Context, M, string) O); ok { r0 = rf(ctx, model, apiView) } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(interface{}) - } + r0 = ret.Get(0).(O) } - if rf, ok := ret.Get(1).(func(context.Context, db_repo.ModelBased, string) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, M, string) error); ok { r1 = rf(ctx, model, apiView) } else { r1 = ret.Error(1) @@ -224,31 +146,31 @@ func (_m *CreateHandler) TransformOutput(ctx context.Context, model db_repo.Mode } // CreateHandler_TransformOutput_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'TransformOutput' -type CreateHandler_TransformOutput_Call struct { +type CreateHandler_TransformOutput_Call[I interface{}, O interface{}, K mdl.PossibleIdentifier, M db_repo.ModelBased[K]] struct { *mock.Call } // TransformOutput is a helper method to define mock.On call // - ctx context.Context -// - model db_repo.ModelBased +// - model M // - apiView string -func (_e *CreateHandler_Expecter) TransformOutput(ctx interface{}, model interface{}, apiView interface{}) *CreateHandler_TransformOutput_Call { - return &CreateHandler_TransformOutput_Call{Call: _e.mock.On("TransformOutput", ctx, model, apiView)} +func (_e *CreateHandler_Expecter[I, O, K, M]) TransformOutput(ctx interface{}, model interface{}, apiView interface{}) *CreateHandler_TransformOutput_Call[I, O, K, M] { + return &CreateHandler_TransformOutput_Call[I, O, K, M]{Call: _e.mock.On("TransformOutput", ctx, model, apiView)} } -func (_c *CreateHandler_TransformOutput_Call) Run(run func(ctx context.Context, model db_repo.ModelBased, apiView string)) *CreateHandler_TransformOutput_Call { +func (_c *CreateHandler_TransformOutput_Call[I, O, K, M]) Run(run func(ctx context.Context, model M, apiView string)) *CreateHandler_TransformOutput_Call[I, O, K, M] { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(db_repo.ModelBased), args[2].(string)) + run(args[0].(context.Context), args[1].(M), args[2].(string)) }) return _c } -func (_c *CreateHandler_TransformOutput_Call) Return(output interface{}, err error) *CreateHandler_TransformOutput_Call { +func (_c *CreateHandler_TransformOutput_Call[I, O, K, M]) Return(output O, err error) *CreateHandler_TransformOutput_Call[I, O, K, M] { _c.Call.Return(output, err) return _c } -func (_c *CreateHandler_TransformOutput_Call) RunAndReturn(run func(context.Context, db_repo.ModelBased, string) (interface{}, error)) *CreateHandler_TransformOutput_Call { +func (_c *CreateHandler_TransformOutput_Call[I, O, K, M]) RunAndReturn(run func(context.Context, M, string) (O, error)) *CreateHandler_TransformOutput_Call[I, O, K, M] { _c.Call.Return(run) return _c } @@ -259,8 +181,8 @@ type mockConstructorTestingTNewCreateHandler interface { } // NewCreateHandler creates a new instance of CreateHandler. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewCreateHandler(t mockConstructorTestingTNewCreateHandler) *CreateHandler { - mock := &CreateHandler{} +func NewCreateHandler[I interface{}, O interface{}, K mdl.PossibleIdentifier, M db_repo.ModelBased[K]](t mockConstructorTestingTNewCreateHandler) *CreateHandler[I, O, K, M] { + mock := &CreateHandler[I, O, K, M]{} mock.Mock.Test(t) t.Cleanup(func() { mock.AssertExpectations(t) }) diff --git a/pkg/httpserver/crud/mocks/Handler.go b/pkg/httpserver/crud/mocks/Handler.go index 99fcaac46..0e9496dcf 100644 --- a/pkg/httpserver/crud/mocks/Handler.go +++ b/pkg/httpserver/crud/mocks/Handler.go @@ -6,120 +6,35 @@ import ( context "context" db_repo "github.com/justtrackio/gosoline/pkg/db-repo" - crud "github.com/justtrackio/gosoline/pkg/httpserver/crud" + + mdl "github.com/justtrackio/gosoline/pkg/mdl" mock "github.com/stretchr/testify/mock" ) // Handler is an autogenerated mock type for the Handler type -type Handler struct { +type Handler[CI interface{}, UI interface{}, O interface{}, K mdl.PossibleIdentifier, M db_repo.ModelBased[K]] struct { mock.Mock } -type Handler_Expecter struct { +type Handler_Expecter[CI interface{}, UI interface{}, O interface{}, K mdl.PossibleIdentifier, M db_repo.ModelBased[K]] struct { mock *mock.Mock } -func (_m *Handler) EXPECT() *Handler_Expecter { - return &Handler_Expecter{mock: &_m.Mock} -} - -// GetCreateInput provides a mock function with given fields: -func (_m *Handler) GetCreateInput() interface{} { - ret := _m.Called() - - var r0 interface{} - if rf, ok := ret.Get(0).(func() interface{}); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(interface{}) - } - } - - return r0 -} - -// Handler_GetCreateInput_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetCreateInput' -type Handler_GetCreateInput_Call struct { - *mock.Call -} - -// GetCreateInput is a helper method to define mock.On call -func (_e *Handler_Expecter) GetCreateInput() *Handler_GetCreateInput_Call { - return &Handler_GetCreateInput_Call{Call: _e.mock.On("GetCreateInput")} -} - -func (_c *Handler_GetCreateInput_Call) Run(run func()) *Handler_GetCreateInput_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *Handler_GetCreateInput_Call) Return(_a0 interface{}) *Handler_GetCreateInput_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *Handler_GetCreateInput_Call) RunAndReturn(run func() interface{}) *Handler_GetCreateInput_Call { - _c.Call.Return(run) - return _c -} - -// GetModel provides a mock function with given fields: -func (_m *Handler) GetModel() db_repo.ModelBased { - ret := _m.Called() - - var r0 db_repo.ModelBased - if rf, ok := ret.Get(0).(func() db_repo.ModelBased); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(db_repo.ModelBased) - } - } - - return r0 -} - -// Handler_GetModel_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetModel' -type Handler_GetModel_Call struct { - *mock.Call -} - -// GetModel is a helper method to define mock.On call -func (_e *Handler_Expecter) GetModel() *Handler_GetModel_Call { - return &Handler_GetModel_Call{Call: _e.mock.On("GetModel")} -} - -func (_c *Handler_GetModel_Call) Run(run func()) *Handler_GetModel_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *Handler_GetModel_Call) Return(_a0 db_repo.ModelBased) *Handler_GetModel_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *Handler_GetModel_Call) RunAndReturn(run func() db_repo.ModelBased) *Handler_GetModel_Call { - _c.Call.Return(run) - return _c +func (_m *Handler[CI, UI, O, K, M]) EXPECT() *Handler_Expecter[CI, UI, O, K, M] { + return &Handler_Expecter[CI, UI, O, K, M]{mock: &_m.Mock} } // GetRepository provides a mock function with given fields: -func (_m *Handler) GetRepository() crud.Repository { +func (_m *Handler[CI, UI, O, K, M]) GetRepository() db_repo.Repository[K, M] { ret := _m.Called() - var r0 crud.Repository - if rf, ok := ret.Get(0).(func() crud.Repository); ok { + var r0 db_repo.Repository[K, M] + if rf, ok := ret.Get(0).(func() db_repo.Repository[K, M]); ok { r0 = rf() } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(crud.Repository) + r0 = ret.Get(0).(db_repo.Repository[K, M]) } } @@ -127,89 +42,46 @@ func (_m *Handler) GetRepository() crud.Repository { } // Handler_GetRepository_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetRepository' -type Handler_GetRepository_Call struct { +type Handler_GetRepository_Call[CI interface{}, UI interface{}, O interface{}, K mdl.PossibleIdentifier, M db_repo.ModelBased[K]] struct { *mock.Call } // GetRepository is a helper method to define mock.On call -func (_e *Handler_Expecter) GetRepository() *Handler_GetRepository_Call { - return &Handler_GetRepository_Call{Call: _e.mock.On("GetRepository")} +func (_e *Handler_Expecter[CI, UI, O, K, M]) GetRepository() *Handler_GetRepository_Call[CI, UI, O, K, M] { + return &Handler_GetRepository_Call[CI, UI, O, K, M]{Call: _e.mock.On("GetRepository")} } -func (_c *Handler_GetRepository_Call) Run(run func()) *Handler_GetRepository_Call { +func (_c *Handler_GetRepository_Call[CI, UI, O, K, M]) Run(run func()) *Handler_GetRepository_Call[CI, UI, O, K, M] { _c.Call.Run(func(args mock.Arguments) { run() }) return _c } -func (_c *Handler_GetRepository_Call) Return(_a0 crud.Repository) *Handler_GetRepository_Call { +func (_c *Handler_GetRepository_Call[CI, UI, O, K, M]) Return(_a0 db_repo.Repository[K, M]) *Handler_GetRepository_Call[CI, UI, O, K, M] { _c.Call.Return(_a0) return _c } -func (_c *Handler_GetRepository_Call) RunAndReturn(run func() crud.Repository) *Handler_GetRepository_Call { - _c.Call.Return(run) - return _c -} - -// GetUpdateInput provides a mock function with given fields: -func (_m *Handler) GetUpdateInput() interface{} { - ret := _m.Called() - - var r0 interface{} - if rf, ok := ret.Get(0).(func() interface{}); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(interface{}) - } - } - - return r0 -} - -// Handler_GetUpdateInput_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetUpdateInput' -type Handler_GetUpdateInput_Call struct { - *mock.Call -} - -// GetUpdateInput is a helper method to define mock.On call -func (_e *Handler_Expecter) GetUpdateInput() *Handler_GetUpdateInput_Call { - return &Handler_GetUpdateInput_Call{Call: _e.mock.On("GetUpdateInput")} -} - -func (_c *Handler_GetUpdateInput_Call) Run(run func()) *Handler_GetUpdateInput_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *Handler_GetUpdateInput_Call) Return(_a0 interface{}) *Handler_GetUpdateInput_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *Handler_GetUpdateInput_Call) RunAndReturn(run func() interface{}) *Handler_GetUpdateInput_Call { +func (_c *Handler_GetRepository_Call[CI, UI, O, K, M]) RunAndReturn(run func() db_repo.Repository[K, M]) *Handler_GetRepository_Call[CI, UI, O, K, M] { _c.Call.Return(run) return _c } // List provides a mock function with given fields: ctx, qb, apiView -func (_m *Handler) List(ctx context.Context, qb *db_repo.QueryBuilder, apiView string) (interface{}, error) { +func (_m *Handler[CI, UI, O, K, M]) List(ctx context.Context, qb *db_repo.QueryBuilder, apiView string) ([]O, error) { ret := _m.Called(ctx, qb, apiView) - var r0 interface{} + var r0 []O var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *db_repo.QueryBuilder, string) (interface{}, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, *db_repo.QueryBuilder, string) ([]O, error)); ok { return rf(ctx, qb, apiView) } - if rf, ok := ret.Get(0).(func(context.Context, *db_repo.QueryBuilder, string) interface{}); ok { + if rf, ok := ret.Get(0).(func(context.Context, *db_repo.QueryBuilder, string) []O); ok { r0 = rf(ctx, qb, apiView) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(interface{}) + r0 = ret.Get(0).([]O) } } @@ -223,7 +95,7 @@ func (_m *Handler) List(ctx context.Context, qb *db_repo.QueryBuilder, apiView s } // Handler_List_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'List' -type Handler_List_Call struct { +type Handler_List_Call[CI interface{}, UI interface{}, O interface{}, K mdl.PossibleIdentifier, M db_repo.ModelBased[K]] struct { *mock.Call } @@ -231,89 +103,96 @@ type Handler_List_Call struct { // - ctx context.Context // - qb *db_repo.QueryBuilder // - apiView string -func (_e *Handler_Expecter) List(ctx interface{}, qb interface{}, apiView interface{}) *Handler_List_Call { - return &Handler_List_Call{Call: _e.mock.On("List", ctx, qb, apiView)} +func (_e *Handler_Expecter[CI, UI, O, K, M]) List(ctx interface{}, qb interface{}, apiView interface{}) *Handler_List_Call[CI, UI, O, K, M] { + return &Handler_List_Call[CI, UI, O, K, M]{Call: _e.mock.On("List", ctx, qb, apiView)} } -func (_c *Handler_List_Call) Run(run func(ctx context.Context, qb *db_repo.QueryBuilder, apiView string)) *Handler_List_Call { +func (_c *Handler_List_Call[CI, UI, O, K, M]) Run(run func(ctx context.Context, qb *db_repo.QueryBuilder, apiView string)) *Handler_List_Call[CI, UI, O, K, M] { _c.Call.Run(func(args mock.Arguments) { run(args[0].(context.Context), args[1].(*db_repo.QueryBuilder), args[2].(string)) }) return _c } -func (_c *Handler_List_Call) Return(out interface{}, err error) *Handler_List_Call { +func (_c *Handler_List_Call[CI, UI, O, K, M]) Return(out []O, err error) *Handler_List_Call[CI, UI, O, K, M] { _c.Call.Return(out, err) return _c } -func (_c *Handler_List_Call) RunAndReturn(run func(context.Context, *db_repo.QueryBuilder, string) (interface{}, error)) *Handler_List_Call { +func (_c *Handler_List_Call[CI, UI, O, K, M]) RunAndReturn(run func(context.Context, *db_repo.QueryBuilder, string) ([]O, error)) *Handler_List_Call[CI, UI, O, K, M] { _c.Call.Return(run) return _c } -// TransformCreate provides a mock function with given fields: ctx, input, model -func (_m *Handler) TransformCreate(ctx context.Context, input interface{}, model db_repo.ModelBased) error { - ret := _m.Called(ctx, input, model) +// TransformCreate provides a mock function with given fields: ctx, input +func (_m *Handler[CI, UI, O, K, M]) TransformCreate(ctx context.Context, input *CI) (M, error) { + ret := _m.Called(ctx, input) - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, interface{}, db_repo.ModelBased) error); ok { - r0 = rf(ctx, input, model) + var r0 M + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *CI) (M, error)); ok { + return rf(ctx, input) + } + if rf, ok := ret.Get(0).(func(context.Context, *CI) M); ok { + r0 = rf(ctx, input) } else { - r0 = ret.Error(0) + r0 = ret.Get(0).(M) } - return r0 + if rf, ok := ret.Get(1).(func(context.Context, *CI) error); ok { + r1 = rf(ctx, input) + } else { + r1 = ret.Error(1) + } + + return r0, r1 } // Handler_TransformCreate_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'TransformCreate' -type Handler_TransformCreate_Call struct { +type Handler_TransformCreate_Call[CI interface{}, UI interface{}, O interface{}, K mdl.PossibleIdentifier, M db_repo.ModelBased[K]] struct { *mock.Call } // TransformCreate is a helper method to define mock.On call // - ctx context.Context -// - input interface{} -// - model db_repo.ModelBased -func (_e *Handler_Expecter) TransformCreate(ctx interface{}, input interface{}, model interface{}) *Handler_TransformCreate_Call { - return &Handler_TransformCreate_Call{Call: _e.mock.On("TransformCreate", ctx, input, model)} +// - input *CI +func (_e *Handler_Expecter[CI, UI, O, K, M]) TransformCreate(ctx interface{}, input interface{}) *Handler_TransformCreate_Call[CI, UI, O, K, M] { + return &Handler_TransformCreate_Call[CI, UI, O, K, M]{Call: _e.mock.On("TransformCreate", ctx, input)} } -func (_c *Handler_TransformCreate_Call) Run(run func(ctx context.Context, input interface{}, model db_repo.ModelBased)) *Handler_TransformCreate_Call { +func (_c *Handler_TransformCreate_Call[CI, UI, O, K, M]) Run(run func(ctx context.Context, input *CI)) *Handler_TransformCreate_Call[CI, UI, O, K, M] { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(interface{}), args[2].(db_repo.ModelBased)) + run(args[0].(context.Context), args[1].(*CI)) }) return _c } -func (_c *Handler_TransformCreate_Call) Return(err error) *Handler_TransformCreate_Call { - _c.Call.Return(err) +func (_c *Handler_TransformCreate_Call[CI, UI, O, K, M]) Return(_a0 M, _a1 error) *Handler_TransformCreate_Call[CI, UI, O, K, M] { + _c.Call.Return(_a0, _a1) return _c } -func (_c *Handler_TransformCreate_Call) RunAndReturn(run func(context.Context, interface{}, db_repo.ModelBased) error) *Handler_TransformCreate_Call { +func (_c *Handler_TransformCreate_Call[CI, UI, O, K, M]) RunAndReturn(run func(context.Context, *CI) (M, error)) *Handler_TransformCreate_Call[CI, UI, O, K, M] { _c.Call.Return(run) return _c } // TransformOutput provides a mock function with given fields: ctx, model, apiView -func (_m *Handler) TransformOutput(ctx context.Context, model db_repo.ModelBased, apiView string) (interface{}, error) { +func (_m *Handler[CI, UI, O, K, M]) TransformOutput(ctx context.Context, model M, apiView string) (O, error) { ret := _m.Called(ctx, model, apiView) - var r0 interface{} + var r0 O var r1 error - if rf, ok := ret.Get(0).(func(context.Context, db_repo.ModelBased, string) (interface{}, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, M, string) (O, error)); ok { return rf(ctx, model, apiView) } - if rf, ok := ret.Get(0).(func(context.Context, db_repo.ModelBased, string) interface{}); ok { + if rf, ok := ret.Get(0).(func(context.Context, M, string) O); ok { r0 = rf(ctx, model, apiView) } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(interface{}) - } + r0 = ret.Get(0).(O) } - if rf, ok := ret.Get(1).(func(context.Context, db_repo.ModelBased, string) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, M, string) error); ok { r1 = rf(ctx, model, apiView) } else { r1 = ret.Error(1) @@ -323,75 +202,85 @@ func (_m *Handler) TransformOutput(ctx context.Context, model db_repo.ModelBased } // Handler_TransformOutput_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'TransformOutput' -type Handler_TransformOutput_Call struct { +type Handler_TransformOutput_Call[CI interface{}, UI interface{}, O interface{}, K mdl.PossibleIdentifier, M db_repo.ModelBased[K]] struct { *mock.Call } // TransformOutput is a helper method to define mock.On call // - ctx context.Context -// - model db_repo.ModelBased +// - model M // - apiView string -func (_e *Handler_Expecter) TransformOutput(ctx interface{}, model interface{}, apiView interface{}) *Handler_TransformOutput_Call { - return &Handler_TransformOutput_Call{Call: _e.mock.On("TransformOutput", ctx, model, apiView)} +func (_e *Handler_Expecter[CI, UI, O, K, M]) TransformOutput(ctx interface{}, model interface{}, apiView interface{}) *Handler_TransformOutput_Call[CI, UI, O, K, M] { + return &Handler_TransformOutput_Call[CI, UI, O, K, M]{Call: _e.mock.On("TransformOutput", ctx, model, apiView)} } -func (_c *Handler_TransformOutput_Call) Run(run func(ctx context.Context, model db_repo.ModelBased, apiView string)) *Handler_TransformOutput_Call { +func (_c *Handler_TransformOutput_Call[CI, UI, O, K, M]) Run(run func(ctx context.Context, model M, apiView string)) *Handler_TransformOutput_Call[CI, UI, O, K, M] { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(db_repo.ModelBased), args[2].(string)) + run(args[0].(context.Context), args[1].(M), args[2].(string)) }) return _c } -func (_c *Handler_TransformOutput_Call) Return(output interface{}, err error) *Handler_TransformOutput_Call { +func (_c *Handler_TransformOutput_Call[CI, UI, O, K, M]) Return(output O, err error) *Handler_TransformOutput_Call[CI, UI, O, K, M] { _c.Call.Return(output, err) return _c } -func (_c *Handler_TransformOutput_Call) RunAndReturn(run func(context.Context, db_repo.ModelBased, string) (interface{}, error)) *Handler_TransformOutput_Call { +func (_c *Handler_TransformOutput_Call[CI, UI, O, K, M]) RunAndReturn(run func(context.Context, M, string) (O, error)) *Handler_TransformOutput_Call[CI, UI, O, K, M] { _c.Call.Return(run) return _c } // TransformUpdate provides a mock function with given fields: ctx, input, model -func (_m *Handler) TransformUpdate(ctx context.Context, input interface{}, model db_repo.ModelBased) error { +func (_m *Handler[CI, UI, O, K, M]) TransformUpdate(ctx context.Context, input *UI, model M) (M, error) { ret := _m.Called(ctx, input, model) - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, interface{}, db_repo.ModelBased) error); ok { + var r0 M + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *UI, M) (M, error)); ok { + return rf(ctx, input, model) + } + if rf, ok := ret.Get(0).(func(context.Context, *UI, M) M); ok { r0 = rf(ctx, input, model) } else { - r0 = ret.Error(0) + r0 = ret.Get(0).(M) } - return r0 + if rf, ok := ret.Get(1).(func(context.Context, *UI, M) error); ok { + r1 = rf(ctx, input, model) + } else { + r1 = ret.Error(1) + } + + return r0, r1 } // Handler_TransformUpdate_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'TransformUpdate' -type Handler_TransformUpdate_Call struct { +type Handler_TransformUpdate_Call[CI interface{}, UI interface{}, O interface{}, K mdl.PossibleIdentifier, M db_repo.ModelBased[K]] struct { *mock.Call } // TransformUpdate is a helper method to define mock.On call // - ctx context.Context -// - input interface{} -// - model db_repo.ModelBased -func (_e *Handler_Expecter) TransformUpdate(ctx interface{}, input interface{}, model interface{}) *Handler_TransformUpdate_Call { - return &Handler_TransformUpdate_Call{Call: _e.mock.On("TransformUpdate", ctx, input, model)} +// - input *UI +// - model M +func (_e *Handler_Expecter[CI, UI, O, K, M]) TransformUpdate(ctx interface{}, input interface{}, model interface{}) *Handler_TransformUpdate_Call[CI, UI, O, K, M] { + return &Handler_TransformUpdate_Call[CI, UI, O, K, M]{Call: _e.mock.On("TransformUpdate", ctx, input, model)} } -func (_c *Handler_TransformUpdate_Call) Run(run func(ctx context.Context, input interface{}, model db_repo.ModelBased)) *Handler_TransformUpdate_Call { +func (_c *Handler_TransformUpdate_Call[CI, UI, O, K, M]) Run(run func(ctx context.Context, input *UI, model M)) *Handler_TransformUpdate_Call[CI, UI, O, K, M] { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(interface{}), args[2].(db_repo.ModelBased)) + run(args[0].(context.Context), args[1].(*UI), args[2].(M)) }) return _c } -func (_c *Handler_TransformUpdate_Call) Return(err error) *Handler_TransformUpdate_Call { - _c.Call.Return(err) +func (_c *Handler_TransformUpdate_Call[CI, UI, O, K, M]) Return(_a0 M, _a1 error) *Handler_TransformUpdate_Call[CI, UI, O, K, M] { + _c.Call.Return(_a0, _a1) return _c } -func (_c *Handler_TransformUpdate_Call) RunAndReturn(run func(context.Context, interface{}, db_repo.ModelBased) error) *Handler_TransformUpdate_Call { +func (_c *Handler_TransformUpdate_Call[CI, UI, O, K, M]) RunAndReturn(run func(context.Context, *UI, M) (M, error)) *Handler_TransformUpdate_Call[CI, UI, O, K, M] { _c.Call.Return(run) return _c } @@ -402,8 +291,8 @@ type mockConstructorTestingTNewHandler interface { } // NewHandler creates a new instance of Handler. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewHandler(t mockConstructorTestingTNewHandler) *Handler { - mock := &Handler{} +func NewHandler[CI interface{}, UI interface{}, O interface{}, K mdl.PossibleIdentifier, M db_repo.ModelBased[K]](t mockConstructorTestingTNewHandler) *Handler[CI, UI, O, K, M] { + mock := &Handler[CI, UI, O, K, M]{} mock.Mock.Test(t) t.Cleanup(func() { mock.AssertExpectations(t) }) diff --git a/pkg/httpserver/crud/mocks/ListHandler.go b/pkg/httpserver/crud/mocks/ListHandler.go index df2e8e885..745a8d54d 100644 --- a/pkg/httpserver/crud/mocks/ListHandler.go +++ b/pkg/httpserver/crud/mocks/ListHandler.go @@ -6,77 +6,35 @@ import ( context "context" db_repo "github.com/justtrackio/gosoline/pkg/db-repo" - crud "github.com/justtrackio/gosoline/pkg/httpserver/crud" + + mdl "github.com/justtrackio/gosoline/pkg/mdl" mock "github.com/stretchr/testify/mock" ) // ListHandler is an autogenerated mock type for the ListHandler type -type ListHandler struct { +type ListHandler[O interface{}, K mdl.PossibleIdentifier, M db_repo.ModelBased[K]] struct { mock.Mock } -type ListHandler_Expecter struct { +type ListHandler_Expecter[O interface{}, K mdl.PossibleIdentifier, M db_repo.ModelBased[K]] struct { mock *mock.Mock } -func (_m *ListHandler) EXPECT() *ListHandler_Expecter { - return &ListHandler_Expecter{mock: &_m.Mock} -} - -// GetModel provides a mock function with given fields: -func (_m *ListHandler) GetModel() db_repo.ModelBased { - ret := _m.Called() - - var r0 db_repo.ModelBased - if rf, ok := ret.Get(0).(func() db_repo.ModelBased); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(db_repo.ModelBased) - } - } - - return r0 -} - -// ListHandler_GetModel_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetModel' -type ListHandler_GetModel_Call struct { - *mock.Call -} - -// GetModel is a helper method to define mock.On call -func (_e *ListHandler_Expecter) GetModel() *ListHandler_GetModel_Call { - return &ListHandler_GetModel_Call{Call: _e.mock.On("GetModel")} -} - -func (_c *ListHandler_GetModel_Call) Run(run func()) *ListHandler_GetModel_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *ListHandler_GetModel_Call) Return(_a0 db_repo.ModelBased) *ListHandler_GetModel_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *ListHandler_GetModel_Call) RunAndReturn(run func() db_repo.ModelBased) *ListHandler_GetModel_Call { - _c.Call.Return(run) - return _c +func (_m *ListHandler[O, K, M]) EXPECT() *ListHandler_Expecter[O, K, M] { + return &ListHandler_Expecter[O, K, M]{mock: &_m.Mock} } // GetRepository provides a mock function with given fields: -func (_m *ListHandler) GetRepository() crud.Repository { +func (_m *ListHandler[O, K, M]) GetRepository() db_repo.Repository[K, M] { ret := _m.Called() - var r0 crud.Repository - if rf, ok := ret.Get(0).(func() crud.Repository); ok { + var r0 db_repo.Repository[K, M] + if rf, ok := ret.Get(0).(func() db_repo.Repository[K, M]); ok { r0 = rf() } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(crud.Repository) + r0 = ret.Get(0).(db_repo.Repository[K, M]) } } @@ -84,46 +42,46 @@ func (_m *ListHandler) GetRepository() crud.Repository { } // ListHandler_GetRepository_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetRepository' -type ListHandler_GetRepository_Call struct { +type ListHandler_GetRepository_Call[O interface{}, K mdl.PossibleIdentifier, M db_repo.ModelBased[K]] struct { *mock.Call } // GetRepository is a helper method to define mock.On call -func (_e *ListHandler_Expecter) GetRepository() *ListHandler_GetRepository_Call { - return &ListHandler_GetRepository_Call{Call: _e.mock.On("GetRepository")} +func (_e *ListHandler_Expecter[O, K, M]) GetRepository() *ListHandler_GetRepository_Call[O, K, M] { + return &ListHandler_GetRepository_Call[O, K, M]{Call: _e.mock.On("GetRepository")} } -func (_c *ListHandler_GetRepository_Call) Run(run func()) *ListHandler_GetRepository_Call { +func (_c *ListHandler_GetRepository_Call[O, K, M]) Run(run func()) *ListHandler_GetRepository_Call[O, K, M] { _c.Call.Run(func(args mock.Arguments) { run() }) return _c } -func (_c *ListHandler_GetRepository_Call) Return(_a0 crud.Repository) *ListHandler_GetRepository_Call { +func (_c *ListHandler_GetRepository_Call[O, K, M]) Return(_a0 db_repo.Repository[K, M]) *ListHandler_GetRepository_Call[O, K, M] { _c.Call.Return(_a0) return _c } -func (_c *ListHandler_GetRepository_Call) RunAndReturn(run func() crud.Repository) *ListHandler_GetRepository_Call { +func (_c *ListHandler_GetRepository_Call[O, K, M]) RunAndReturn(run func() db_repo.Repository[K, M]) *ListHandler_GetRepository_Call[O, K, M] { _c.Call.Return(run) return _c } // List provides a mock function with given fields: ctx, qb, apiView -func (_m *ListHandler) List(ctx context.Context, qb *db_repo.QueryBuilder, apiView string) (interface{}, error) { +func (_m *ListHandler[O, K, M]) List(ctx context.Context, qb *db_repo.QueryBuilder, apiView string) ([]O, error) { ret := _m.Called(ctx, qb, apiView) - var r0 interface{} + var r0 []O var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *db_repo.QueryBuilder, string) (interface{}, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, *db_repo.QueryBuilder, string) ([]O, error)); ok { return rf(ctx, qb, apiView) } - if rf, ok := ret.Get(0).(func(context.Context, *db_repo.QueryBuilder, string) interface{}); ok { + if rf, ok := ret.Get(0).(func(context.Context, *db_repo.QueryBuilder, string) []O); ok { r0 = rf(ctx, qb, apiView) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(interface{}) + r0 = ret.Get(0).([]O) } } @@ -137,7 +95,7 @@ func (_m *ListHandler) List(ctx context.Context, qb *db_repo.QueryBuilder, apiVi } // ListHandler_List_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'List' -type ListHandler_List_Call struct { +type ListHandler_List_Call[O interface{}, K mdl.PossibleIdentifier, M db_repo.ModelBased[K]] struct { *mock.Call } @@ -145,45 +103,43 @@ type ListHandler_List_Call struct { // - ctx context.Context // - qb *db_repo.QueryBuilder // - apiView string -func (_e *ListHandler_Expecter) List(ctx interface{}, qb interface{}, apiView interface{}) *ListHandler_List_Call { - return &ListHandler_List_Call{Call: _e.mock.On("List", ctx, qb, apiView)} +func (_e *ListHandler_Expecter[O, K, M]) List(ctx interface{}, qb interface{}, apiView interface{}) *ListHandler_List_Call[O, K, M] { + return &ListHandler_List_Call[O, K, M]{Call: _e.mock.On("List", ctx, qb, apiView)} } -func (_c *ListHandler_List_Call) Run(run func(ctx context.Context, qb *db_repo.QueryBuilder, apiView string)) *ListHandler_List_Call { +func (_c *ListHandler_List_Call[O, K, M]) Run(run func(ctx context.Context, qb *db_repo.QueryBuilder, apiView string)) *ListHandler_List_Call[O, K, M] { _c.Call.Run(func(args mock.Arguments) { run(args[0].(context.Context), args[1].(*db_repo.QueryBuilder), args[2].(string)) }) return _c } -func (_c *ListHandler_List_Call) Return(out interface{}, err error) *ListHandler_List_Call { +func (_c *ListHandler_List_Call[O, K, M]) Return(out []O, err error) *ListHandler_List_Call[O, K, M] { _c.Call.Return(out, err) return _c } -func (_c *ListHandler_List_Call) RunAndReturn(run func(context.Context, *db_repo.QueryBuilder, string) (interface{}, error)) *ListHandler_List_Call { +func (_c *ListHandler_List_Call[O, K, M]) RunAndReturn(run func(context.Context, *db_repo.QueryBuilder, string) ([]O, error)) *ListHandler_List_Call[O, K, M] { _c.Call.Return(run) return _c } // TransformOutput provides a mock function with given fields: ctx, model, apiView -func (_m *ListHandler) TransformOutput(ctx context.Context, model db_repo.ModelBased, apiView string) (interface{}, error) { +func (_m *ListHandler[O, K, M]) TransformOutput(ctx context.Context, model M, apiView string) (O, error) { ret := _m.Called(ctx, model, apiView) - var r0 interface{} + var r0 O var r1 error - if rf, ok := ret.Get(0).(func(context.Context, db_repo.ModelBased, string) (interface{}, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, M, string) (O, error)); ok { return rf(ctx, model, apiView) } - if rf, ok := ret.Get(0).(func(context.Context, db_repo.ModelBased, string) interface{}); ok { + if rf, ok := ret.Get(0).(func(context.Context, M, string) O); ok { r0 = rf(ctx, model, apiView) } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(interface{}) - } + r0 = ret.Get(0).(O) } - if rf, ok := ret.Get(1).(func(context.Context, db_repo.ModelBased, string) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, M, string) error); ok { r1 = rf(ctx, model, apiView) } else { r1 = ret.Error(1) @@ -193,31 +149,31 @@ func (_m *ListHandler) TransformOutput(ctx context.Context, model db_repo.ModelB } // ListHandler_TransformOutput_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'TransformOutput' -type ListHandler_TransformOutput_Call struct { +type ListHandler_TransformOutput_Call[O interface{}, K mdl.PossibleIdentifier, M db_repo.ModelBased[K]] struct { *mock.Call } // TransformOutput is a helper method to define mock.On call // - ctx context.Context -// - model db_repo.ModelBased +// - model M // - apiView string -func (_e *ListHandler_Expecter) TransformOutput(ctx interface{}, model interface{}, apiView interface{}) *ListHandler_TransformOutput_Call { - return &ListHandler_TransformOutput_Call{Call: _e.mock.On("TransformOutput", ctx, model, apiView)} +func (_e *ListHandler_Expecter[O, K, M]) TransformOutput(ctx interface{}, model interface{}, apiView interface{}) *ListHandler_TransformOutput_Call[O, K, M] { + return &ListHandler_TransformOutput_Call[O, K, M]{Call: _e.mock.On("TransformOutput", ctx, model, apiView)} } -func (_c *ListHandler_TransformOutput_Call) Run(run func(ctx context.Context, model db_repo.ModelBased, apiView string)) *ListHandler_TransformOutput_Call { +func (_c *ListHandler_TransformOutput_Call[O, K, M]) Run(run func(ctx context.Context, model M, apiView string)) *ListHandler_TransformOutput_Call[O, K, M] { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(db_repo.ModelBased), args[2].(string)) + run(args[0].(context.Context), args[1].(M), args[2].(string)) }) return _c } -func (_c *ListHandler_TransformOutput_Call) Return(output interface{}, err error) *ListHandler_TransformOutput_Call { +func (_c *ListHandler_TransformOutput_Call[O, K, M]) Return(output O, err error) *ListHandler_TransformOutput_Call[O, K, M] { _c.Call.Return(output, err) return _c } -func (_c *ListHandler_TransformOutput_Call) RunAndReturn(run func(context.Context, db_repo.ModelBased, string) (interface{}, error)) *ListHandler_TransformOutput_Call { +func (_c *ListHandler_TransformOutput_Call[O, K, M]) RunAndReturn(run func(context.Context, M, string) (O, error)) *ListHandler_TransformOutput_Call[O, K, M] { _c.Call.Return(run) return _c } @@ -228,8 +184,8 @@ type mockConstructorTestingTNewListHandler interface { } // NewListHandler creates a new instance of ListHandler. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewListHandler(t mockConstructorTestingTNewListHandler) *ListHandler { - mock := &ListHandler{} +func NewListHandler[O interface{}, K mdl.PossibleIdentifier, M db_repo.ModelBased[K]](t mockConstructorTestingTNewListHandler) *ListHandler[O, K, M] { + mock := &ListHandler[O, K, M]{} mock.Mock.Test(t) t.Cleanup(func() { mock.AssertExpectations(t) }) diff --git a/pkg/httpserver/crud/mocks/Repository.go b/pkg/httpserver/crud/mocks/Repository.go deleted file mode 100644 index 3e82f5aff..000000000 --- a/pkg/httpserver/crud/mocks/Repository.go +++ /dev/null @@ -1,351 +0,0 @@ -// Code generated by mockery v2.22.1. DO NOT EDIT. - -package mocks - -import ( - context "context" - - db_repo "github.com/justtrackio/gosoline/pkg/db-repo" - - mock "github.com/stretchr/testify/mock" -) - -// Repository is an autogenerated mock type for the Repository type -type Repository struct { - mock.Mock -} - -type Repository_Expecter struct { - mock *mock.Mock -} - -func (_m *Repository) EXPECT() *Repository_Expecter { - return &Repository_Expecter{mock: &_m.Mock} -} - -// Count provides a mock function with given fields: ctx, qb, model -func (_m *Repository) Count(ctx context.Context, qb *db_repo.QueryBuilder, model db_repo.ModelBased) (int, error) { - ret := _m.Called(ctx, qb, model) - - var r0 int - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *db_repo.QueryBuilder, db_repo.ModelBased) (int, error)); ok { - return rf(ctx, qb, model) - } - if rf, ok := ret.Get(0).(func(context.Context, *db_repo.QueryBuilder, db_repo.ModelBased) int); ok { - r0 = rf(ctx, qb, model) - } else { - r0 = ret.Get(0).(int) - } - - if rf, ok := ret.Get(1).(func(context.Context, *db_repo.QueryBuilder, db_repo.ModelBased) error); ok { - r1 = rf(ctx, qb, model) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// Repository_Count_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Count' -type Repository_Count_Call struct { - *mock.Call -} - -// Count is a helper method to define mock.On call -// - ctx context.Context -// - qb *db_repo.QueryBuilder -// - model db_repo.ModelBased -func (_e *Repository_Expecter) Count(ctx interface{}, qb interface{}, model interface{}) *Repository_Count_Call { - return &Repository_Count_Call{Call: _e.mock.On("Count", ctx, qb, model)} -} - -func (_c *Repository_Count_Call) Run(run func(ctx context.Context, qb *db_repo.QueryBuilder, model db_repo.ModelBased)) *Repository_Count_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(*db_repo.QueryBuilder), args[2].(db_repo.ModelBased)) - }) - return _c -} - -func (_c *Repository_Count_Call) Return(_a0 int, _a1 error) *Repository_Count_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *Repository_Count_Call) RunAndReturn(run func(context.Context, *db_repo.QueryBuilder, db_repo.ModelBased) (int, error)) *Repository_Count_Call { - _c.Call.Return(run) - return _c -} - -// Create provides a mock function with given fields: ctx, value -func (_m *Repository) Create(ctx context.Context, value db_repo.ModelBased) error { - ret := _m.Called(ctx, value) - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, db_repo.ModelBased) error); ok { - r0 = rf(ctx, value) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// Repository_Create_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Create' -type Repository_Create_Call struct { - *mock.Call -} - -// Create is a helper method to define mock.On call -// - ctx context.Context -// - value db_repo.ModelBased -func (_e *Repository_Expecter) Create(ctx interface{}, value interface{}) *Repository_Create_Call { - return &Repository_Create_Call{Call: _e.mock.On("Create", ctx, value)} -} - -func (_c *Repository_Create_Call) Run(run func(ctx context.Context, value db_repo.ModelBased)) *Repository_Create_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(db_repo.ModelBased)) - }) - return _c -} - -func (_c *Repository_Create_Call) Return(_a0 error) *Repository_Create_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *Repository_Create_Call) RunAndReturn(run func(context.Context, db_repo.ModelBased) error) *Repository_Create_Call { - _c.Call.Return(run) - return _c -} - -// Delete provides a mock function with given fields: ctx, value -func (_m *Repository) Delete(ctx context.Context, value db_repo.ModelBased) error { - ret := _m.Called(ctx, value) - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, db_repo.ModelBased) error); ok { - r0 = rf(ctx, value) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// Repository_Delete_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Delete' -type Repository_Delete_Call struct { - *mock.Call -} - -// Delete is a helper method to define mock.On call -// - ctx context.Context -// - value db_repo.ModelBased -func (_e *Repository_Expecter) Delete(ctx interface{}, value interface{}) *Repository_Delete_Call { - return &Repository_Delete_Call{Call: _e.mock.On("Delete", ctx, value)} -} - -func (_c *Repository_Delete_Call) Run(run func(ctx context.Context, value db_repo.ModelBased)) *Repository_Delete_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(db_repo.ModelBased)) - }) - return _c -} - -func (_c *Repository_Delete_Call) Return(_a0 error) *Repository_Delete_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *Repository_Delete_Call) RunAndReturn(run func(context.Context, db_repo.ModelBased) error) *Repository_Delete_Call { - _c.Call.Return(run) - return _c -} - -// GetMetadata provides a mock function with given fields: -func (_m *Repository) GetMetadata() db_repo.Metadata { - ret := _m.Called() - - var r0 db_repo.Metadata - if rf, ok := ret.Get(0).(func() db_repo.Metadata); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(db_repo.Metadata) - } - - return r0 -} - -// Repository_GetMetadata_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetMetadata' -type Repository_GetMetadata_Call struct { - *mock.Call -} - -// GetMetadata is a helper method to define mock.On call -func (_e *Repository_Expecter) GetMetadata() *Repository_GetMetadata_Call { - return &Repository_GetMetadata_Call{Call: _e.mock.On("GetMetadata")} -} - -func (_c *Repository_GetMetadata_Call) Run(run func()) *Repository_GetMetadata_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *Repository_GetMetadata_Call) Return(_a0 db_repo.Metadata) *Repository_GetMetadata_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *Repository_GetMetadata_Call) RunAndReturn(run func() db_repo.Metadata) *Repository_GetMetadata_Call { - _c.Call.Return(run) - return _c -} - -// Query provides a mock function with given fields: ctx, qb, result -func (_m *Repository) Query(ctx context.Context, qb *db_repo.QueryBuilder, result interface{}) error { - ret := _m.Called(ctx, qb, result) - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, *db_repo.QueryBuilder, interface{}) error); ok { - r0 = rf(ctx, qb, result) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// Repository_Query_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Query' -type Repository_Query_Call struct { - *mock.Call -} - -// Query is a helper method to define mock.On call -// - ctx context.Context -// - qb *db_repo.QueryBuilder -// - result interface{} -func (_e *Repository_Expecter) Query(ctx interface{}, qb interface{}, result interface{}) *Repository_Query_Call { - return &Repository_Query_Call{Call: _e.mock.On("Query", ctx, qb, result)} -} - -func (_c *Repository_Query_Call) Run(run func(ctx context.Context, qb *db_repo.QueryBuilder, result interface{})) *Repository_Query_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(*db_repo.QueryBuilder), args[2].(interface{})) - }) - return _c -} - -func (_c *Repository_Query_Call) Return(_a0 error) *Repository_Query_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *Repository_Query_Call) RunAndReturn(run func(context.Context, *db_repo.QueryBuilder, interface{}) error) *Repository_Query_Call { - _c.Call.Return(run) - return _c -} - -// Read provides a mock function with given fields: ctx, id, out -func (_m *Repository) Read(ctx context.Context, id *uint, out db_repo.ModelBased) error { - ret := _m.Called(ctx, id, out) - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, *uint, db_repo.ModelBased) error); ok { - r0 = rf(ctx, id, out) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// Repository_Read_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Read' -type Repository_Read_Call struct { - *mock.Call -} - -// Read is a helper method to define mock.On call -// - ctx context.Context -// - id *uint -// - out db_repo.ModelBased -func (_e *Repository_Expecter) Read(ctx interface{}, id interface{}, out interface{}) *Repository_Read_Call { - return &Repository_Read_Call{Call: _e.mock.On("Read", ctx, id, out)} -} - -func (_c *Repository_Read_Call) Run(run func(ctx context.Context, id *uint, out db_repo.ModelBased)) *Repository_Read_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(*uint), args[2].(db_repo.ModelBased)) - }) - return _c -} - -func (_c *Repository_Read_Call) Return(_a0 error) *Repository_Read_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *Repository_Read_Call) RunAndReturn(run func(context.Context, *uint, db_repo.ModelBased) error) *Repository_Read_Call { - _c.Call.Return(run) - return _c -} - -// Update provides a mock function with given fields: ctx, value -func (_m *Repository) Update(ctx context.Context, value db_repo.ModelBased) error { - ret := _m.Called(ctx, value) - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, db_repo.ModelBased) error); ok { - r0 = rf(ctx, value) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// Repository_Update_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Update' -type Repository_Update_Call struct { - *mock.Call -} - -// Update is a helper method to define mock.On call -// - ctx context.Context -// - value db_repo.ModelBased -func (_e *Repository_Expecter) Update(ctx interface{}, value interface{}) *Repository_Update_Call { - return &Repository_Update_Call{Call: _e.mock.On("Update", ctx, value)} -} - -func (_c *Repository_Update_Call) Run(run func(ctx context.Context, value db_repo.ModelBased)) *Repository_Update_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(db_repo.ModelBased)) - }) - return _c -} - -func (_c *Repository_Update_Call) Return(_a0 error) *Repository_Update_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *Repository_Update_Call) RunAndReturn(run func(context.Context, db_repo.ModelBased) error) *Repository_Update_Call { - _c.Call.Return(run) - return _c -} - -type mockConstructorTestingTNewRepository interface { - mock.TestingT - Cleanup(func()) -} - -// NewRepository creates a new instance of Repository. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewRepository(t mockConstructorTestingTNewRepository) *Repository { - mock := &Repository{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/pkg/httpserver/crud/mocks/UpdateHandler.go b/pkg/httpserver/crud/mocks/UpdateHandler.go index 57f3f80fd..8d66d8a0c 100644 --- a/pkg/httpserver/crud/mocks/UpdateHandler.go +++ b/pkg/httpserver/crud/mocks/UpdateHandler.go @@ -6,77 +6,35 @@ import ( context "context" db_repo "github.com/justtrackio/gosoline/pkg/db-repo" - crud "github.com/justtrackio/gosoline/pkg/httpserver/crud" + + mdl "github.com/justtrackio/gosoline/pkg/mdl" mock "github.com/stretchr/testify/mock" ) // UpdateHandler is an autogenerated mock type for the UpdateHandler type -type UpdateHandler struct { +type UpdateHandler[I interface{}, O interface{}, K mdl.PossibleIdentifier, M db_repo.ModelBased[K]] struct { mock.Mock } -type UpdateHandler_Expecter struct { +type UpdateHandler_Expecter[I interface{}, O interface{}, K mdl.PossibleIdentifier, M db_repo.ModelBased[K]] struct { mock *mock.Mock } -func (_m *UpdateHandler) EXPECT() *UpdateHandler_Expecter { - return &UpdateHandler_Expecter{mock: &_m.Mock} -} - -// GetModel provides a mock function with given fields: -func (_m *UpdateHandler) GetModel() db_repo.ModelBased { - ret := _m.Called() - - var r0 db_repo.ModelBased - if rf, ok := ret.Get(0).(func() db_repo.ModelBased); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(db_repo.ModelBased) - } - } - - return r0 -} - -// UpdateHandler_GetModel_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetModel' -type UpdateHandler_GetModel_Call struct { - *mock.Call -} - -// GetModel is a helper method to define mock.On call -func (_e *UpdateHandler_Expecter) GetModel() *UpdateHandler_GetModel_Call { - return &UpdateHandler_GetModel_Call{Call: _e.mock.On("GetModel")} -} - -func (_c *UpdateHandler_GetModel_Call) Run(run func()) *UpdateHandler_GetModel_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *UpdateHandler_GetModel_Call) Return(_a0 db_repo.ModelBased) *UpdateHandler_GetModel_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *UpdateHandler_GetModel_Call) RunAndReturn(run func() db_repo.ModelBased) *UpdateHandler_GetModel_Call { - _c.Call.Return(run) - return _c +func (_m *UpdateHandler[I, O, K, M]) EXPECT() *UpdateHandler_Expecter[I, O, K, M] { + return &UpdateHandler_Expecter[I, O, K, M]{mock: &_m.Mock} } // GetRepository provides a mock function with given fields: -func (_m *UpdateHandler) GetRepository() crud.Repository { +func (_m *UpdateHandler[I, O, K, M]) GetRepository() db_repo.Repository[K, M] { ret := _m.Called() - var r0 crud.Repository - if rf, ok := ret.Get(0).(func() crud.Repository); ok { + var r0 db_repo.Repository[K, M] + if rf, ok := ret.Get(0).(func() db_repo.Repository[K, M]); ok { r0 = rf() } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(crud.Repository) + r0 = ret.Get(0).(db_repo.Repository[K, M]) } } @@ -84,93 +42,48 @@ func (_m *UpdateHandler) GetRepository() crud.Repository { } // UpdateHandler_GetRepository_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetRepository' -type UpdateHandler_GetRepository_Call struct { +type UpdateHandler_GetRepository_Call[I interface{}, O interface{}, K mdl.PossibleIdentifier, M db_repo.ModelBased[K]] struct { *mock.Call } // GetRepository is a helper method to define mock.On call -func (_e *UpdateHandler_Expecter) GetRepository() *UpdateHandler_GetRepository_Call { - return &UpdateHandler_GetRepository_Call{Call: _e.mock.On("GetRepository")} +func (_e *UpdateHandler_Expecter[I, O, K, M]) GetRepository() *UpdateHandler_GetRepository_Call[I, O, K, M] { + return &UpdateHandler_GetRepository_Call[I, O, K, M]{Call: _e.mock.On("GetRepository")} } -func (_c *UpdateHandler_GetRepository_Call) Run(run func()) *UpdateHandler_GetRepository_Call { +func (_c *UpdateHandler_GetRepository_Call[I, O, K, M]) Run(run func()) *UpdateHandler_GetRepository_Call[I, O, K, M] { _c.Call.Run(func(args mock.Arguments) { run() }) return _c } -func (_c *UpdateHandler_GetRepository_Call) Return(_a0 crud.Repository) *UpdateHandler_GetRepository_Call { +func (_c *UpdateHandler_GetRepository_Call[I, O, K, M]) Return(_a0 db_repo.Repository[K, M]) *UpdateHandler_GetRepository_Call[I, O, K, M] { _c.Call.Return(_a0) return _c } -func (_c *UpdateHandler_GetRepository_Call) RunAndReturn(run func() crud.Repository) *UpdateHandler_GetRepository_Call { - _c.Call.Return(run) - return _c -} - -// GetUpdateInput provides a mock function with given fields: -func (_m *UpdateHandler) GetUpdateInput() interface{} { - ret := _m.Called() - - var r0 interface{} - if rf, ok := ret.Get(0).(func() interface{}); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(interface{}) - } - } - - return r0 -} - -// UpdateHandler_GetUpdateInput_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetUpdateInput' -type UpdateHandler_GetUpdateInput_Call struct { - *mock.Call -} - -// GetUpdateInput is a helper method to define mock.On call -func (_e *UpdateHandler_Expecter) GetUpdateInput() *UpdateHandler_GetUpdateInput_Call { - return &UpdateHandler_GetUpdateInput_Call{Call: _e.mock.On("GetUpdateInput")} -} - -func (_c *UpdateHandler_GetUpdateInput_Call) Run(run func()) *UpdateHandler_GetUpdateInput_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *UpdateHandler_GetUpdateInput_Call) Return(_a0 interface{}) *UpdateHandler_GetUpdateInput_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *UpdateHandler_GetUpdateInput_Call) RunAndReturn(run func() interface{}) *UpdateHandler_GetUpdateInput_Call { +func (_c *UpdateHandler_GetRepository_Call[I, O, K, M]) RunAndReturn(run func() db_repo.Repository[K, M]) *UpdateHandler_GetRepository_Call[I, O, K, M] { _c.Call.Return(run) return _c } // TransformOutput provides a mock function with given fields: ctx, model, apiView -func (_m *UpdateHandler) TransformOutput(ctx context.Context, model db_repo.ModelBased, apiView string) (interface{}, error) { +func (_m *UpdateHandler[I, O, K, M]) TransformOutput(ctx context.Context, model M, apiView string) (O, error) { ret := _m.Called(ctx, model, apiView) - var r0 interface{} + var r0 O var r1 error - if rf, ok := ret.Get(0).(func(context.Context, db_repo.ModelBased, string) (interface{}, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, M, string) (O, error)); ok { return rf(ctx, model, apiView) } - if rf, ok := ret.Get(0).(func(context.Context, db_repo.ModelBased, string) interface{}); ok { + if rf, ok := ret.Get(0).(func(context.Context, M, string) O); ok { r0 = rf(ctx, model, apiView) } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(interface{}) - } + r0 = ret.Get(0).(O) } - if rf, ok := ret.Get(1).(func(context.Context, db_repo.ModelBased, string) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, M, string) error); ok { r1 = rf(ctx, model, apiView) } else { r1 = ret.Error(1) @@ -180,75 +93,85 @@ func (_m *UpdateHandler) TransformOutput(ctx context.Context, model db_repo.Mode } // UpdateHandler_TransformOutput_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'TransformOutput' -type UpdateHandler_TransformOutput_Call struct { +type UpdateHandler_TransformOutput_Call[I interface{}, O interface{}, K mdl.PossibleIdentifier, M db_repo.ModelBased[K]] struct { *mock.Call } // TransformOutput is a helper method to define mock.On call // - ctx context.Context -// - model db_repo.ModelBased +// - model M // - apiView string -func (_e *UpdateHandler_Expecter) TransformOutput(ctx interface{}, model interface{}, apiView interface{}) *UpdateHandler_TransformOutput_Call { - return &UpdateHandler_TransformOutput_Call{Call: _e.mock.On("TransformOutput", ctx, model, apiView)} +func (_e *UpdateHandler_Expecter[I, O, K, M]) TransformOutput(ctx interface{}, model interface{}, apiView interface{}) *UpdateHandler_TransformOutput_Call[I, O, K, M] { + return &UpdateHandler_TransformOutput_Call[I, O, K, M]{Call: _e.mock.On("TransformOutput", ctx, model, apiView)} } -func (_c *UpdateHandler_TransformOutput_Call) Run(run func(ctx context.Context, model db_repo.ModelBased, apiView string)) *UpdateHandler_TransformOutput_Call { +func (_c *UpdateHandler_TransformOutput_Call[I, O, K, M]) Run(run func(ctx context.Context, model M, apiView string)) *UpdateHandler_TransformOutput_Call[I, O, K, M] { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(db_repo.ModelBased), args[2].(string)) + run(args[0].(context.Context), args[1].(M), args[2].(string)) }) return _c } -func (_c *UpdateHandler_TransformOutput_Call) Return(output interface{}, err error) *UpdateHandler_TransformOutput_Call { +func (_c *UpdateHandler_TransformOutput_Call[I, O, K, M]) Return(output O, err error) *UpdateHandler_TransformOutput_Call[I, O, K, M] { _c.Call.Return(output, err) return _c } -func (_c *UpdateHandler_TransformOutput_Call) RunAndReturn(run func(context.Context, db_repo.ModelBased, string) (interface{}, error)) *UpdateHandler_TransformOutput_Call { +func (_c *UpdateHandler_TransformOutput_Call[I, O, K, M]) RunAndReturn(run func(context.Context, M, string) (O, error)) *UpdateHandler_TransformOutput_Call[I, O, K, M] { _c.Call.Return(run) return _c } // TransformUpdate provides a mock function with given fields: ctx, input, model -func (_m *UpdateHandler) TransformUpdate(ctx context.Context, input interface{}, model db_repo.ModelBased) error { +func (_m *UpdateHandler[I, O, K, M]) TransformUpdate(ctx context.Context, input *I, model M) (M, error) { ret := _m.Called(ctx, input, model) - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, interface{}, db_repo.ModelBased) error); ok { + var r0 M + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *I, M) (M, error)); ok { + return rf(ctx, input, model) + } + if rf, ok := ret.Get(0).(func(context.Context, *I, M) M); ok { r0 = rf(ctx, input, model) } else { - r0 = ret.Error(0) + r0 = ret.Get(0).(M) } - return r0 + if rf, ok := ret.Get(1).(func(context.Context, *I, M) error); ok { + r1 = rf(ctx, input, model) + } else { + r1 = ret.Error(1) + } + + return r0, r1 } // UpdateHandler_TransformUpdate_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'TransformUpdate' -type UpdateHandler_TransformUpdate_Call struct { +type UpdateHandler_TransformUpdate_Call[I interface{}, O interface{}, K mdl.PossibleIdentifier, M db_repo.ModelBased[K]] struct { *mock.Call } // TransformUpdate is a helper method to define mock.On call // - ctx context.Context -// - input interface{} -// - model db_repo.ModelBased -func (_e *UpdateHandler_Expecter) TransformUpdate(ctx interface{}, input interface{}, model interface{}) *UpdateHandler_TransformUpdate_Call { - return &UpdateHandler_TransformUpdate_Call{Call: _e.mock.On("TransformUpdate", ctx, input, model)} +// - input *I +// - model M +func (_e *UpdateHandler_Expecter[I, O, K, M]) TransformUpdate(ctx interface{}, input interface{}, model interface{}) *UpdateHandler_TransformUpdate_Call[I, O, K, M] { + return &UpdateHandler_TransformUpdate_Call[I, O, K, M]{Call: _e.mock.On("TransformUpdate", ctx, input, model)} } -func (_c *UpdateHandler_TransformUpdate_Call) Run(run func(ctx context.Context, input interface{}, model db_repo.ModelBased)) *UpdateHandler_TransformUpdate_Call { +func (_c *UpdateHandler_TransformUpdate_Call[I, O, K, M]) Run(run func(ctx context.Context, input *I, model M)) *UpdateHandler_TransformUpdate_Call[I, O, K, M] { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(interface{}), args[2].(db_repo.ModelBased)) + run(args[0].(context.Context), args[1].(*I), args[2].(M)) }) return _c } -func (_c *UpdateHandler_TransformUpdate_Call) Return(err error) *UpdateHandler_TransformUpdate_Call { - _c.Call.Return(err) +func (_c *UpdateHandler_TransformUpdate_Call[I, O, K, M]) Return(_a0 M, _a1 error) *UpdateHandler_TransformUpdate_Call[I, O, K, M] { + _c.Call.Return(_a0, _a1) return _c } -func (_c *UpdateHandler_TransformUpdate_Call) RunAndReturn(run func(context.Context, interface{}, db_repo.ModelBased) error) *UpdateHandler_TransformUpdate_Call { +func (_c *UpdateHandler_TransformUpdate_Call[I, O, K, M]) RunAndReturn(run func(context.Context, *I, M) (M, error)) *UpdateHandler_TransformUpdate_Call[I, O, K, M] { _c.Call.Return(run) return _c } @@ -259,8 +182,8 @@ type mockConstructorTestingTNewUpdateHandler interface { } // NewUpdateHandler creates a new instance of UpdateHandler. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewUpdateHandler(t mockConstructorTestingTNewUpdateHandler) *UpdateHandler { - mock := &UpdateHandler{} +func NewUpdateHandler[I interface{}, O interface{}, K mdl.PossibleIdentifier, M db_repo.ModelBased[K]](t mockConstructorTestingTNewUpdateHandler) *UpdateHandler[I, O, K, M] { + mock := &UpdateHandler[I, O, K, M]{} mock.Mock.Test(t) t.Cleanup(func() { mock.AssertExpectations(t) }) diff --git a/pkg/httpserver/crud/read.go b/pkg/httpserver/crud/read.go index 6113f9eb4..e14b5ca74 100644 --- a/pkg/httpserver/crud/read.go +++ b/pkg/httpserver/crud/read.go @@ -5,19 +5,20 @@ import ( "net/http" "github.com/gin-gonic/gin" - "github.com/justtrackio/gosoline/pkg/db-repo" + dbRepo "github.com/justtrackio/gosoline/pkg/db-repo" "github.com/justtrackio/gosoline/pkg/httpserver" "github.com/justtrackio/gosoline/pkg/log" + "github.com/justtrackio/gosoline/pkg/mdl" "github.com/pkg/errors" ) -type readHandler struct { +type readHandler[O any, K mdl.PossibleIdentifier, M dbRepo.ModelBased[K]] struct { logger log.Logger - transformer BaseHandler + transformer BaseHandler[O, K, M] } -func NewReadHandler(logger log.Logger, transformer BaseHandler) gin.HandlerFunc { - rh := readHandler{ +func NewReadHandler[O any, K mdl.PossibleIdentifier, M dbRepo.ModelBased[K]](logger log.Logger, transformer BaseHandler[O, K, M]) gin.HandlerFunc { + rh := readHandler[O, K, M]{ transformer: transformer, logger: logger, } @@ -25,18 +26,17 @@ func NewReadHandler(logger log.Logger, transformer BaseHandler) gin.HandlerFunc return httpserver.CreateHandler(rh) } -func (rh readHandler) Handle(ctx context.Context, request *httpserver.Request) (*httpserver.Response, error) { - id, valid := httpserver.GetUintFromRequest(request, "id") +func (rh readHandler[O, K, M]) Handle(ctx context.Context, request *httpserver.Request) (*httpserver.Response, error) { + id, valid := httpserver.GetIdentifierFromRequest[K](request, "id") if !valid { return nil, errors.New("no valid id provided") } repo := rh.transformer.GetRepository() - model := rh.transformer.GetModel() - err := repo.Read(ctx, id, model) + model, err := repo.Read(ctx, *id) - var notFound db_repo.RecordNotFoundError + var notFound dbRepo.RecordNotFoundError if errors.As(err, ¬Found) { rh.logger.WithContext(ctx).Warn("failed to read model: %s", err) diff --git a/pkg/httpserver/crud/update.go b/pkg/httpserver/crud/update.go index fc9b62098..f724b02de 100644 --- a/pkg/httpserver/crud/update.go +++ b/pkg/httpserver/crud/update.go @@ -7,19 +7,20 @@ import ( "github.com/gin-gonic/gin" "github.com/justtrackio/gosoline/pkg/db" - "github.com/justtrackio/gosoline/pkg/db-repo" + dbRepo "github.com/justtrackio/gosoline/pkg/db-repo" "github.com/justtrackio/gosoline/pkg/httpserver" "github.com/justtrackio/gosoline/pkg/log" + "github.com/justtrackio/gosoline/pkg/mdl" "github.com/justtrackio/gosoline/pkg/validation" ) -type updateHandler struct { +type updateHandler[I any, O any, K mdl.PossibleIdentifier, M dbRepo.ModelBased[K]] struct { logger log.Logger - transformer UpdateHandler + transformer UpdateHandler[I, O, K, M] } -func NewUpdateHandler(logger log.Logger, transformer UpdateHandler) gin.HandlerFunc { - uh := updateHandler{ +func NewUpdateHandler[I any, O any, K mdl.PossibleIdentifier, M dbRepo.ModelBased[K]](logger log.Logger, transformer UpdateHandler[I, O, K, M]) gin.HandlerFunc { + uh := updateHandler[I, O, K, M]{ transformer: transformer, logger: logger, } @@ -27,22 +28,23 @@ func NewUpdateHandler(logger log.Logger, transformer UpdateHandler) gin.HandlerF return httpserver.CreateJsonHandler(uh) } -func (uh updateHandler) GetInput() interface{} { - return uh.transformer.GetUpdateInput() +func (uh updateHandler[I, O, K, M]) GetInput() interface{} { + var input I + + return &input } -func (uh updateHandler) Handle(ctx context.Context, request *httpserver.Request) (*httpserver.Response, error) { - id, valid := httpserver.GetUintFromRequest(request, "id") +func (uh updateHandler[I, O, K, M]) Handle(ctx context.Context, request *httpserver.Request) (*httpserver.Response, error) { + id, valid := httpserver.GetIdentifierFromRequest[K](request, "id") if !valid { return nil, errors.New("no valid id provided") } repo := uh.transformer.GetRepository() - model := uh.transformer.GetModel() - err := repo.Read(ctx, id, model) + model, err := repo.Read(ctx, *id) - var notFound db_repo.RecordNotFoundError + var notFound dbRepo.RecordNotFoundError if errors.As(err, ¬Found) { uh.logger.WithContext(ctx).Warn("failed to update model: %s", err.Error()) @@ -53,7 +55,7 @@ func (uh updateHandler) Handle(ctx context.Context, request *httpserver.Request) return nil, err } - err = uh.transformer.TransformUpdate(ctx, request.Body, model) + model, err = uh.transformer.TransformUpdate(ctx, request.Body.(*I), model) if modelNotChanged(err) { return httpserver.NewStatusResponse(http.StatusNotModified), nil @@ -77,9 +79,7 @@ func (uh updateHandler) Handle(ctx context.Context, request *httpserver.Request) return nil, err } - reload := uh.transformer.GetModel() - err = repo.Read(ctx, model.GetId(), reload) - + reload, err := repo.Read(ctx, *model.GetId()) if err != nil { return nil, err } diff --git a/pkg/httpserver/param_reader.go b/pkg/httpserver/param_reader.go index ebe60e882..d12b0e6fd 100644 --- a/pkg/httpserver/param_reader.go +++ b/pkg/httpserver/param_reader.go @@ -1,6 +1,7 @@ package httpserver import ( + "fmt" "strconv" "github.com/justtrackio/gosoline/pkg/mdl" @@ -30,3 +31,23 @@ func GetStringFromRequest(request *Request, name string) (*string, bool) { return ¶mString, true } + +func GetIdentifierFromRequest[K mdl.PossibleIdentifier](request *Request, name string) (*K, bool) { + var k K + var ki any = k + + switch ki.(type) { + case string: + id, valid := GetStringFromRequest(request, name) + var idVal any = id + + return idVal.(*K), valid + case uint: + id, valid := GetUintFromRequest(request, name) + var idVal any = id + + return idVal.(*K), valid + default: + panic(fmt.Errorf("type K should either be uint or string, got %T", k)) + } +} diff --git a/pkg/kafka/consumer/settings.go b/pkg/kafka/consumer/settings.go index d8b5261fb..4036be583 100644 --- a/pkg/kafka/consumer/settings.go +++ b/pkg/kafka/consumer/settings.go @@ -5,7 +5,6 @@ import ( "github.com/justtrackio/gosoline/pkg/cfg" "github.com/justtrackio/gosoline/pkg/kafka" - "github.com/justtrackio/gosoline/pkg/kafka/connection" ) diff --git a/pkg/kafka/producer/settings.go b/pkg/kafka/producer/settings.go index 6becb209b..7477745fa 100644 --- a/pkg/kafka/producer/settings.go +++ b/pkg/kafka/producer/settings.go @@ -4,7 +4,6 @@ import ( "time" "github.com/justtrackio/gosoline/pkg/cfg" - "github.com/justtrackio/gosoline/pkg/kafka" "github.com/justtrackio/gosoline/pkg/kafka/connection" ) diff --git a/pkg/kafka/producer/writer.go b/pkg/kafka/producer/writer.go index c964f0cca..86366dbb5 100644 --- a/pkg/kafka/producer/writer.go +++ b/pkg/kafka/producer/writer.go @@ -6,7 +6,6 @@ import ( "github.com/justtrackio/gosoline/pkg/kafka/logging" "github.com/justtrackio/gosoline/pkg/log" - "github.com/segmentio/kafka-go" ) diff --git a/pkg/log/mocks/factory.go b/pkg/log/mocks/factory.go index b0698eb85..a001e092b 100644 --- a/pkg/log/mocks/factory.go +++ b/pkg/log/mocks/factory.go @@ -10,9 +10,9 @@ import ( func NewLoggerMock() *Logger { logger := new(Logger) - logger.On("WithChannel", mock.AnythingOfType("string")).Return(logger).Maybe() - logger.On("WithContext", mock.Anything).Return(logger).Maybe() - logger.On("WithFields", mock.Anything).Return(logger).Maybe() + logger.EXPECT().WithChannel(mock.AnythingOfType("string")).Return(logger).Maybe() + logger.EXPECT().WithContext(mock.Anything).Return(logger).Maybe() + logger.EXPECT().WithFields(mock.Anything).Return(logger).Maybe() return logger } @@ -21,32 +21,46 @@ func NewLoggerMockedAll() *Logger { return NewLoggerMockedUntilLevel(log.PriorityError) } -// return a logger mocked up to the given log level. All other calls will cause an error and fail the test. +// NewLoggerMockedUntilLevel returns a logger mocked up to the given log level. All other calls will cause an error and fail the test. func NewLoggerMockedUntilLevel(level int) *Logger { logger := NewLoggerMock() - mockLoggerMethod(logger, "Debug", log.LevelDebug, level >= log.PriorityDebug) - mockLoggerMethod(logger, "Info", log.LevelInfo, level >= log.PriorityInfo) - mockLoggerMethod(logger, "Warn", log.LevelWarn, level >= log.PriorityWarn) - mockLoggerMethod(logger, "Error", log.LevelError, level >= log.PriorityError) + mockLoggerMethod(logger.EXPECT().Debug, log.LevelDebug, level >= log.PriorityDebug) + mockLoggerMethod(logger.EXPECT().Info, log.LevelInfo, level >= log.PriorityInfo) + mockLoggerMethod(logger.EXPECT().Warn, log.LevelWarn, level >= log.PriorityWarn) + mockLoggerMethod(logger.EXPECT().Error, log.LevelError, level >= log.PriorityError) return logger } -func mockLoggerMethod(logger *Logger, method string, level string, allowed bool) { +type call[C call2[C]] interface { + call2[C] + Run(run func(format string, args ...interface{})) C +} + +type call2[C call3] interface { + call3 + Return() C +} + +type call3 interface { + Maybe() *mock.Call +} + +func mockLoggerMethod[C call[C]](method func(format interface{}, args ...interface{}) C, level string, allowed bool) { anythings := make(mock.Arguments, 0) f := inspectLogFunction(level, allowed) for i := 0; i < 10; i++ { + method(mock.AnythingOfType("string"), anythings...).Run(f).Return().Maybe() anythings = append(anythings, mock.Anything) - logger.On(method, anythings...).Run(f).Return(logger).Maybe() } } -func inspectLogFunction(level string, allowed bool) func(args mock.Arguments) { - return func(args mock.Arguments) { +func inspectLogFunction(level string, allowed bool) func(format string, args ...interface{}) { + return func(format string, args ...interface{}) { if !allowed { - panic(fmt.Errorf("invalid log message '%s'. Logs of level %s are not allowed", args.Get(0), level)) + panic(fmt.Errorf("invalid log message '%s' and parameters %v. Logs of level %s are not allowed", format, args, level)) } } } diff --git a/pkg/mdl/model.go b/pkg/mdl/model.go index 042c88f1a..9991b2d7a 100644 --- a/pkg/mdl/model.go +++ b/pkg/mdl/model.go @@ -61,19 +61,19 @@ func ModelIdFromString(str string) (ModelId, error) { return modelId, nil } -type Identifiable interface { - GetId() *uint +type PossibleIdentifier interface { + uint | string } -type Keyed interface { - GetKey() string +type Identifiable[K PossibleIdentifier] interface { + GetId() *K } -type Identifier struct { - Id *uint `json:"id" binding:"required"` +type Identifier[K PossibleIdentifier] struct { + Id *K `json:"id" binding:"required"` } -func (i *Identifier) GetId() *uint { +func (i *Identifier[K]) GetId() *K { if i == nil { return nil } @@ -81,8 +81,8 @@ func (i *Identifier) GetId() *uint { return i.Id } -func WithIdentifier(id *uint) *Identifier { - return &Identifier{ +func WithIdentifier[K PossibleIdentifier](id *K) *Identifier[K] { + return &Identifier[K]{ Id: id, } } diff --git a/pkg/mdl/named.go b/pkg/mdl/named.go index e1d92a685..1967ed5ac 100644 --- a/pkg/mdl/named.go +++ b/pkg/mdl/named.go @@ -8,7 +8,7 @@ type NamedOutputV0 struct { } type Nameable interface { - Identifiable + Identifiable[uint] GetName() *string } diff --git a/pkg/share/create.go b/pkg/share/create.go index 6e12fe693..da26fa206 100644 --- a/pkg/share/create.go +++ b/pkg/share/create.go @@ -11,18 +11,19 @@ import ( "github.com/justtrackio/gosoline/pkg/httpserver" "github.com/justtrackio/gosoline/pkg/httpserver/crud" "github.com/justtrackio/gosoline/pkg/log" + "github.com/justtrackio/gosoline/pkg/mdl" "github.com/justtrackio/gosoline/pkg/uuid" "github.com/justtrackio/gosoline/pkg/validation" ) -type shareCreateHandler struct { +type shareCreateHandler[I Metadata, K mdl.PossibleIdentifier, M Shareable[K]] struct { logger log.Logger - transformer ShareCreateHandler + transformer ShareCreateHandler[I, K, M] uuidProvider uuid.Uuid } -func NewShareCreateHandler(logger log.Logger, transformer ShareCreateHandler) gin.HandlerFunc { - sh := shareCreateHandler{ +func NewShareCreateHandler[I Metadata, K mdl.PossibleIdentifier, M Shareable[K]](logger log.Logger, transformer ShareCreateHandler[I, K, M]) gin.HandlerFunc { + sh := shareCreateHandler[I, K, M]{ logger: logger, transformer: transformer, uuidProvider: uuid.New(), @@ -31,19 +32,21 @@ func NewShareCreateHandler(logger log.Logger, transformer ShareCreateHandler) gi return httpserver.CreateJsonHandler(sh) } -func (s shareCreateHandler) GetInput() interface{} { - return s.transformer.GetCreateInput() +func (s shareCreateHandler[I, K, M]) GetInput() interface{} { + var input I + + return &input } -func (s shareCreateHandler) Handle(ctx context.Context, req *httpserver.Request) (*httpserver.Response, error) { +func (s shareCreateHandler[I, K, M]) Handle(ctx context.Context, req *httpserver.Request) (*httpserver.Response, error) { logger := s.logger.WithContext(ctx) - id, valid := httpserver.GetUintFromRequest(req, "id") + id, valid := httpserver.GetIdentifierFromRequest[K](req, "id") if !valid { return nil, errors.New("no valid id provided") } - entity, err := s.getEntity(ctx, id) + entity, err := s.getEntity(ctx, *id) var notFound db_repo.RecordNotFoundError if errors.As(err, ¬Found) { logger.Warn("failed to read entity: %s", err.Error()) @@ -55,10 +58,9 @@ func (s shareCreateHandler) Handle(ctx context.Context, req *httpserver.Request) return nil, err } - model := s.transformer.GetModel() // we assert cast safely here as the req.Body will get parsed in something that implements Metadata - shareInput := req.Body.(Metadata) - policy := BuildSharePolicy(s.uuidProvider.NewV4(), entity, shareInput.GetOwnerId(), shareInput.GetActions()) + shareInput := *req.Body.(*I) + policy := BuildSharePolicy[K](s.uuidProvider.NewV4(), entity, shareInput.GetOwnerId(), shareInput.GetActions()) guard := s.transformer.GetGuard() err = guard.CreatePolicy(ctx, policy) @@ -66,7 +68,7 @@ func (s shareCreateHandler) Handle(ctx context.Context, req *httpserver.Request) return nil, err } - err = s.transformer.TransformCreate(ctx, req.Body, entity, policy, model) + model, err := s.transformer.TransformCreate(ctx, shareInput, entity, policy) if err != nil { return nil, err } @@ -86,9 +88,7 @@ func (s shareCreateHandler) Handle(ctx context.Context, req *httpserver.Request) return nil, err } - reload := s.transformer.GetModel() - err = shareRepo.Read(ctx, model.GetId(), reload) - + reload, err := shareRepo.Read(ctx, *model.GetId()) if err != nil { return nil, err } @@ -102,14 +102,8 @@ func (s shareCreateHandler) Handle(ctx context.Context, req *httpserver.Request) return httpserver.NewJsonResponse(out), nil } -func (s shareCreateHandler) getEntity(ctx context.Context, id *uint) (Shareable, error) { - entity := s.transformer.GetEntityModel() +func (s shareCreateHandler[I, K, M]) getEntity(ctx context.Context, id K) (M, error) { entityRepo := s.transformer.GetEntityRepository() - err := entityRepo.Read(ctx, id, entity) - if err != nil { - return nil, err - } - - return entity, nil + return entityRepo.Read(ctx, id) } diff --git a/pkg/share/handler.go b/pkg/share/handler.go index f358726a2..97acbccfe 100644 --- a/pkg/share/handler.go +++ b/pkg/share/handler.go @@ -9,11 +9,12 @@ import ( "github.com/justtrackio/gosoline/pkg/httpserver" "github.com/justtrackio/gosoline/pkg/httpserver/crud" "github.com/justtrackio/gosoline/pkg/log" + "github.com/justtrackio/gosoline/pkg/mdl" "github.com/selm0/ladon" ) -type Shareable interface { - db_repo.ModelBased +type Shareable[K mdl.PossibleIdentifier] interface { + db_repo.ModelBased[K] GetResources() []string GetEntityType() string } @@ -23,36 +24,33 @@ type Metadata interface { GetActions() []string } -type ModelBased interface { - db_repo.ModelBased +type ModelBased[K mdl.PossibleIdentifier] interface { + db_repo.ModelBased[K] GetPolicyId() string } -type BaseShareHandler interface { - GetEntityModel() Shareable - GetEntityRepository() db_repo.Repository +type BaseShareHandler[K mdl.PossibleIdentifier, M Shareable[K]] interface { + GetEntityRepository() db_repo.Repository[K, M] GetGuard() guard.Guard - GetModel() ModelBased - GetRepository() db_repo.Repository - TransformOutput(ctx context.Context, model db_repo.ModelBased, apiView string) (output interface{}, err error) + GetRepository() db_repo.Repository[K, M] + TransformOutput(ctx context.Context, model M, apiView string) (output interface{}, err error) } -type EntityUpdateHandler interface { - BaseShareHandler - crud.BaseUpdateHandler +type EntityUpdateHandler[I any, O any, K mdl.PossibleIdentifier, M Shareable[K]] interface { + BaseShareHandler[K, M] + crud.BaseUpdateHandler[I, K, M] } -type EntityDeleteHandler interface { - BaseShareHandler +type EntityDeleteHandler[K mdl.PossibleIdentifier, M Shareable[K]] interface { + BaseShareHandler[K, M] } -type ShareCreateHandler interface { - BaseShareHandler - GetCreateInput() Metadata - TransformCreate(ctx context.Context, input interface{}, entity Shareable, policy ladon.Policy, model db_repo.ModelBased) (err error) +type ShareCreateHandler[I Metadata, K mdl.PossibleIdentifier, M Shareable[K]] interface { + BaseShareHandler[K, M] + TransformCreate(ctx context.Context, input I, entity Shareable[K], policy ladon.Policy) (model M, err error) } -func AddShareCreateHandler(logger log.Logger, d *httpserver.Definitions, version int, basePath string, handler ShareCreateHandler) { +func AddShareCreateHandler[I Metadata, K mdl.PossibleIdentifier, M Shareable[K]](logger log.Logger, d *httpserver.Definitions, version int, basePath string, handler ShareCreateHandler[I, K, M]) { path := fmt.Sprintf("/v%d/%s/:id/share", version, basePath) - d.POST(path, NewShareCreateHandler(logger, handler)) + d.POST(path, NewShareCreateHandler[I, K, M](logger, handler)) } diff --git a/pkg/share/options.go b/pkg/share/options.go index 543613908..dc1ffd74e 100644 --- a/pkg/share/options.go +++ b/pkg/share/options.go @@ -21,6 +21,7 @@ func KernelMiddlewareShares(ctx context.Context, config cfg.Config, logger log.L return func() { if err := manager.SetupShareTable(); err != nil { logger.Error("can not setup share tables: %s", err.Error()) + return } diff --git a/pkg/share/policy_builder.go b/pkg/share/policy_builder.go index 3a512670d..4d5b02dd6 100644 --- a/pkg/share/policy_builder.go +++ b/pkg/share/policy_builder.go @@ -3,13 +3,14 @@ package share import ( "fmt" + "github.com/justtrackio/gosoline/pkg/mdl" "github.com/selm0/ladon" ) -func BuildSharePolicy(uuid string, entity Shareable, ownerId uint, actions []string) ladon.Policy { +func BuildSharePolicy[K mdl.PossibleIdentifier](uuid string, entity Shareable[K], ownerId uint, actions []string) ladon.Policy { return &ladon.DefaultPolicy{ ID: uuid, - Description: fmt.Sprintf("entity %d shared with owner %d", *entity.GetId(), ownerId), + Description: fmt.Sprintf("entity %v shared with owner %d", *entity.GetId(), ownerId), Subjects: []string{ fmt.Sprintf("a:%d", ownerId), }, diff --git a/pkg/share/repository.go b/pkg/share/repository.go index 838226813..8392e8bff 100644 --- a/pkg/share/repository.go +++ b/pkg/share/repository.go @@ -19,17 +19,17 @@ type WithPolicy interface { type repositoryCtxKey string type sqlRepository struct { - db_repo.Repository + db_repo.Repository[uint, *Share] guard guard.Guard } -func ProvideRepository(ctx context.Context, config cfg.Config, logger log.Logger) (db_repo.Repository, error) { - return appctx.Provide(ctx, repositoryCtxKey("ShareRepository"), func() (db_repo.Repository, error) { +func ProvideRepository(ctx context.Context, config cfg.Config, logger log.Logger) (db_repo.Repository[uint, *Share], error) { + return appctx.Provide(ctx, repositoryCtxKey("ShareRepository"), func() (db_repo.Repository[uint, *Share], error) { return newRepository(config, logger) }) } -func newRepository(config cfg.Config, logger log.Logger) (db_repo.Repository, error) { +func newRepository(config cfg.Config, logger log.Logger) (db_repo.Repository[uint, *Share], error) { var settings Settings config.UnmarshalKey("shares", &settings) tn := settings.TableName @@ -51,7 +51,7 @@ func newRepository(config cfg.Config, logger log.Logger) (db_repo.Repository, er }, } - repo, err := db_repo.New(config, logger, dbSettings) + repo, err := db_repo.New[uint, *Share](config, logger, dbSettings) if err != nil { return nil, fmt.Errorf("can not create repository: %w", err) } @@ -67,18 +67,13 @@ func newRepository(config cfg.Config, logger log.Logger) (db_repo.Repository, er }, nil } -func (r sqlRepository) Delete(ctx context.Context, value db_repo.ModelBased) error { - s, ok := value.(WithPolicy) - if !ok { - return fmt.Errorf("can not get policy id from given entity") - } - +func (r sqlRepository) Delete(ctx context.Context, value *Share) error { err := r.Repository.Delete(ctx, value) if err != nil { return err } - err = r.guard.DeletePolicy(ctx, &ladon.DefaultPolicy{ID: s.GetPolicyId()}) + err = r.guard.DeletePolicy(ctx, &ladon.DefaultPolicy{ID: value.GetPolicyId()}) if err != nil { return err } diff --git a/pkg/share/shareable_repository.go b/pkg/share/shareable_repository.go index 4fbacdda6..e9639e2f8 100644 --- a/pkg/share/shareable_repository.go +++ b/pkg/share/shareable_repository.go @@ -8,17 +8,18 @@ import ( "github.com/justtrackio/gosoline/pkg/db-repo" "github.com/justtrackio/gosoline/pkg/guard" "github.com/justtrackio/gosoline/pkg/log" + "github.com/justtrackio/gosoline/pkg/mdl" "github.com/selm0/ladon" ) -type shareRepository struct { - db_repo.Repository +type shareRepository[K mdl.PossibleIdentifier, M Shareable[K]] struct { + db_repo.Repository[K, M] guard guard.Guard logger log.Logger - shareRepository db_repo.Repository + shareRepository db_repo.Repository[uint, *Share] } -func NewShareableRepository(ctx context.Context, config cfg.Config, logger log.Logger, repo db_repo.Repository) (*shareRepository, error) { +func NewShareableRepository[K mdl.PossibleIdentifier, M Shareable[K]](ctx context.Context, config cfg.Config, logger log.Logger, repo db_repo.Repository[K, M]) (*shareRepository[K, M], error) { guard, err := guard.NewGuard(config, logger) if err != nil { return nil, fmt.Errorf("can not create guard: %w", err) @@ -29,7 +30,7 @@ func NewShareableRepository(ctx context.Context, config cfg.Config, logger log.L return nil, fmt.Errorf("can not create share repository: %w", err) } - return &shareRepository{ + return &shareRepository[K, M]{ Repository: repo, logger: logger, guard: guard, @@ -37,13 +38,8 @@ func NewShareableRepository(ctx context.Context, config cfg.Config, logger log.L }, nil } -func (r shareRepository) Update(ctx context.Context, value db_repo.ModelBased) error { - entity, ok := value.(Shareable) - if !ok { - return fmt.Errorf("can not get entity name from given value") - } - - err := r.Repository.Update(ctx, value) +func (r shareRepository[K, M]) Update(ctx context.Context, entity M) error { + err := r.Repository.Update(ctx, entity) if err != nil { return err } @@ -59,7 +55,7 @@ func (r shareRepository) Update(ctx context.Context, value db_repo.ModelBased) e return fmt.Errorf("can not get policy by id: %w", err) } - updatedPolicy := BuildSharePolicy(share.PolicyId, entity, share.OwnerId, oldPolicy.GetActions()) + updatedPolicy := BuildSharePolicy[K](share.PolicyId, entity, share.OwnerId, oldPolicy.GetActions()) err = r.guard.UpdatePolicy(ctx, updatedPolicy) if err != nil { return fmt.Errorf("can not update policy: %w", err) @@ -69,12 +65,7 @@ func (r shareRepository) Update(ctx context.Context, value db_repo.ModelBased) e return nil } -func (r shareRepository) Delete(ctx context.Context, value db_repo.ModelBased) error { - entity, ok := value.(Shareable) - if !ok { - return fmt.Errorf("can not get entity name from given value") - } - +func (r shareRepository[K, M]) Delete(ctx context.Context, entity M) error { shares, err := r.getEntityShares(ctx, entity) if err != nil { return err @@ -92,15 +83,14 @@ func (r shareRepository) Delete(ctx context.Context, value db_repo.ModelBased) e } } - return r.Repository.Delete(ctx, value) + return r.Repository.Delete(ctx, entity) } -func (r shareRepository) getEntityShares(ctx context.Context, entity Shareable) ([]*Share, error) { +func (r shareRepository[K, M]) getEntityShares(ctx context.Context, entity M) ([]*Share, error) { qb := db_repo.NewQueryBuilder() qb.Where("entity_id = ? and entity_type = ?", *entity.GetId(), entity.GetEntityType()) - var result []*Share - err := r.shareRepository.Query(ctx, qb, &result) + result, err := r.shareRepository.Query(ctx, qb) if err != nil { return nil, fmt.Errorf("can not query shares of entity type %s: %w", entity.GetEntityType(), err) } diff --git a/pkg/stream/message_kafka_test.go b/pkg/stream/message_kafka_test.go index 38fbcb4cb..6d183e94f 100644 --- a/pkg/stream/message_kafka_test.go +++ b/pkg/stream/message_kafka_test.go @@ -5,9 +5,8 @@ import ( "testing" "github.com/justtrackio/gosoline/pkg/stream" - "github.com/stretchr/testify/assert" - "github.com/segmentio/kafka-go" + "github.com/stretchr/testify/assert" ) func Test_NewKafkaMessageAttrs(t *testing.T) { diff --git a/pkg/tracing/tracer_aws.go b/pkg/tracing/tracer_aws.go index f11733de4..c07b5bda1 100644 --- a/pkg/tracing/tracer_aws.go +++ b/pkg/tracing/tracer_aws.go @@ -179,6 +179,7 @@ func lookupAddr(appId cfg.AppId, settings *TracerSettings) string { for _, srv := range srvs { addressValue = fmt.Sprintf("%v:%v", srv.Target, srv.Port) + break } } diff --git a/pkg/validation/operation_repository_db.go b/pkg/validation/operation_repository_db.go index 77132ab31..fa999ce63 100644 --- a/pkg/validation/operation_repository_db.go +++ b/pkg/validation/operation_repository_db.go @@ -3,23 +3,24 @@ package validation import ( "context" - "github.com/justtrackio/gosoline/pkg/db-repo" + dbRepo "github.com/justtrackio/gosoline/pkg/db-repo" + "github.com/justtrackio/gosoline/pkg/mdl" ) -type OperationValidatingRepository struct { - db_repo.Repository +type OperationValidatingRepository[K mdl.PossibleIdentifier, M dbRepo.ModelBased[K]] struct { + dbRepo.Repository[K, M] validator Validator } -func NewOperationValidatingRepository(validator Validator, repo db_repo.Repository) db_repo.Repository { - return &OperationValidatingRepository{ +func NewOperationValidatingRepository[K mdl.PossibleIdentifier, M dbRepo.ModelBased[K]](validator Validator, repo dbRepo.Repository[K, M]) dbRepo.Repository[K, M] { + return &OperationValidatingRepository[K, M]{ Repository: repo, validator: validator, } } -func (r OperationValidatingRepository) Create(ctx context.Context, value db_repo.ModelBased) error { - err := r.validator.IsValid(ctx, value, db_repo.Create) +func (r OperationValidatingRepository[K, M]) Create(ctx context.Context, value M) error { + err := r.validator.IsValid(ctx, value, dbRepo.Create) if err != nil { return err } @@ -27,8 +28,8 @@ func (r OperationValidatingRepository) Create(ctx context.Context, value db_repo return r.Repository.Create(ctx, value) } -func (r OperationValidatingRepository) Update(ctx context.Context, value db_repo.ModelBased) error { - err := r.validator.IsValid(ctx, value, db_repo.Update) +func (r OperationValidatingRepository[K, M]) Update(ctx context.Context, value M) error { + err := r.validator.IsValid(ctx, value, dbRepo.Update) if err != nil { return err } @@ -36,8 +37,8 @@ func (r OperationValidatingRepository) Update(ctx context.Context, value db_repo return r.Repository.Update(ctx, value) } -func (r OperationValidatingRepository) Delete(ctx context.Context, value db_repo.ModelBased) error { - err := r.validator.IsValid(ctx, value, db_repo.Delete) +func (r OperationValidatingRepository[K, M]) Delete(ctx context.Context, value M) error { + err := r.validator.IsValid(ctx, value, dbRepo.Delete) if err != nil { return err } diff --git a/pkg/validation/repository_db.go b/pkg/validation/repository_db.go index 0b6e2c0e7..474f99238 100644 --- a/pkg/validation/repository_db.go +++ b/pkg/validation/repository_db.go @@ -4,21 +4,22 @@ import ( "context" "github.com/justtrackio/gosoline/pkg/db-repo" + "github.com/justtrackio/gosoline/pkg/mdl" ) -type Repository struct { - db_repo.Repository +type Repository[K mdl.PossibleIdentifier, M db_repo.ModelBased[K]] struct { + db_repo.Repository[K, M] validator Validator } -func NewRepository(validator Validator, repo db_repo.Repository) db_repo.Repository { - return &Repository{ +func NewRepository[K mdl.PossibleIdentifier, M db_repo.ModelBased[K]](validator Validator, repo db_repo.Repository[K, M]) db_repo.Repository[K, M] { + return &Repository[K, M]{ Repository: repo, validator: validator, } } -func (r Repository) Create(ctx context.Context, value db_repo.ModelBased) error { +func (r Repository[K, M]) Create(ctx context.Context, value M) error { err := r.validator.IsValid(ctx, value) if err != nil { return err @@ -29,7 +30,7 @@ func (r Repository) Create(ctx context.Context, value db_repo.ModelBased) error return err } -func (r Repository) Update(ctx context.Context, value db_repo.ModelBased) error { +func (r Repository[K, M]) Update(ctx context.Context, value M) error { err := r.validator.IsValid(ctx, value) if err != nil { return err diff --git a/test/db-repo/change_history/entity/change_history_test.go b/test/db-repo/change_history/entity/change_history_test.go index 11cf8ebe9..7ab28718a 100644 --- a/test/db-repo/change_history/entity/change_history_test.go +++ b/test/db-repo/change_history/entity/change_history_test.go @@ -283,12 +283,10 @@ func (s *ChangeHistoryTestSuite) assertHistory(entityId uint, expected []definit return } - histories := make([]*definitions.ItemsHistory, 0) - qb := db_repo.NewQueryBuilder() qb.Where("id = ?", entityId) - err = repo.Query(s.Env().Context(), qb, &histories) + histories, err := repo.Query(s.Env().Context(), qb) if !s.NoError(err) { return } diff --git a/test/db-repo/change_history/entity/definitions/module.go b/test/db-repo/change_history/entity/definitions/module.go index e90af7696..7c0651948 100644 --- a/test/db-repo/change_history/entity/definitions/module.go +++ b/test/db-repo/change_history/entity/definitions/module.go @@ -14,7 +14,7 @@ import ( type module struct { logger log.Logger - repository db_repo.Repository + repository db_repo.Repository[uint, *Item] input stream.Input } diff --git a/test/db-repo/change_history/entity/definitions/repository.go b/test/db-repo/change_history/entity/definitions/repository.go index 3f0c9590d..a316d2548 100644 --- a/test/db-repo/change_history/entity/definitions/repository.go +++ b/test/db-repo/change_history/entity/definitions/repository.go @@ -29,12 +29,12 @@ type ItemsHistory struct { Item } -func NewRepository(ctx context.Context, config cfg.Config, logger log.Logger) (db_repo.Repository, error) { +func NewRepository(ctx context.Context, config cfg.Config, logger log.Logger) (db_repo.Repository[uint, *Item], error) { settings := db_repo.Settings{ Metadata: tableMetadata, } - repository, err := db_repo.New(config, logger, settings) + repository, err := db_repo.New[uint, *Item](config, logger, settings) if err != nil { return nil, fmt.Errorf("unable to create repository: %w", err) } @@ -52,12 +52,12 @@ func NewRepository(ctx context.Context, config cfg.Config, logger log.Logger) (d return repository, nil } -func NewHistoryRepository(ctx context.Context, config cfg.Config, logger log.Logger) (db_repo.RepositoryReadOnly, error) { +func NewHistoryRepository(ctx context.Context, config cfg.Config, logger log.Logger) (db_repo.RepositoryReadOnly[uint, *ItemsHistory], error) { settings := db_repo.Settings{ Metadata: tableHistoryMetadata, } - repository, err := db_repo.New(config, logger, settings) + repository, err := db_repo.New[uint, *ItemsHistory](config, logger, settings) if err != nil { return nil, fmt.Errorf("unable to create repository: %w", err) } diff --git a/test/db-repo/change_history/schema/change_history_test.go b/test/db-repo/change_history/schema/change_history_test.go index 60690cf25..cf7f591b7 100644 --- a/test/db-repo/change_history/schema/change_history_test.go +++ b/test/db-repo/change_history/schema/change_history_test.go @@ -115,12 +115,12 @@ func (s *ChangeHistoryTestSuite) TestChangeHistoryMigration_Migrate_CreateTable( envConfig := s.Env().Config() envLogger := s.Env().Logger() - modelRepo, err := db_repo.New(envConfig, envLogger, db_repo.Settings{ + modelRepo, err := db_repo.New[uint, *TestModel1](envConfig, envLogger, db_repo.Settings{ Metadata: TestModel1Metadata, }) s.NoError(err) - modelHistoryRepo, err := db_repo.New(envConfig, envLogger, db_repo.Settings{ + modelHistoryRepo, err := db_repo.New[uint, *TestModel1HistoryEntry](envConfig, envLogger, db_repo.Settings{ Metadata: TestHistoryModel1Metadata, }) s.NoError(err) @@ -145,8 +145,7 @@ func (s *ChangeHistoryTestSuite) TestChangeHistoryMigration_Migrate_CreateTable( err = modelRepo.Delete(context.Background(), model) s.NoError(err) - entries := make([]*TestModel1HistoryEntry, 0) - err = modelHistoryRepo.Query(context.Background(), &db_repo.QueryBuilder{}, &entries) + entries, err := modelHistoryRepo.Query(context.Background(), &db_repo.QueryBuilder{}) s.NoError(err) s.Equal(3, len(entries), "expected 3 change history entries") @@ -167,12 +166,12 @@ func (s *ChangeHistoryTestSuite) TestChangeHistoryMigration_Migrate_UpdateTable( envConfig := s.Env().Config() envLogger := s.Env().Logger() - modelRepo, err := db_repo.New(envConfig, envLogger, db_repo.Settings{ + modelRepo, err := db_repo.New[uint, *TestModel2](envConfig, envLogger, db_repo.Settings{ Metadata: TestModel2Metadata, }) s.NoError(err) - modelHistoryRepo, err := db_repo.New(envConfig, envLogger, db_repo.Settings{ + modelHistoryRepo, err := db_repo.New[uint, *TestModel2HistoryEntry](envConfig, envLogger, db_repo.Settings{ Metadata: TestHistoryModel2Metadata, }) s.NoError(err) @@ -199,8 +198,7 @@ func (s *ChangeHistoryTestSuite) TestChangeHistoryMigration_Migrate_UpdateTable( err = modelRepo.Delete(context.Background(), model) s.NoError(err) - entries := make([]*TestModel2HistoryEntry, 0) - err = modelHistoryRepo.Query(context.Background(), &db_repo.QueryBuilder{}, &entries) + entries, err := modelHistoryRepo.Query(context.Background(), &db_repo.QueryBuilder{}) s.NoError(err) s.Equal(3, len(entries), "expected 3 change history entries") @@ -231,6 +229,7 @@ func (s *ChangeHistoryTestSuite) TestChangeHistoryMigration_Migrate_ValidateSche multiErr := &multierror.Error{} if !errors.As(err, &multiErr) { s.FailNow("multi error expected, got %T", err) + return } diff --git a/test/db-repo/query/query_test.go b/test/db-repo/query/query_test.go index 2b8aa02ed..f16752621 100644 --- a/test/db-repo/query/query_test.go +++ b/test/db-repo/query/query_test.go @@ -59,7 +59,7 @@ func (s *DbRepoQueryTestSuite) TestCreateCorrectModel() { envConfig := s.Env().Config() envLogger := s.Env().Logger() - repo, err := db_repo.New(envConfig, envLogger, db_repo.Settings{ + repo, err := db_repo.New[uint, *TestModel](envConfig, envLogger, db_repo.Settings{ Metadata: TestModelMetadata, }) s.NoError(err) @@ -78,18 +78,17 @@ func (s *DbRepoQueryTestSuite) TestCreateCorrectModel() { qb := db_repo.NewQueryBuilder() qb.Where(where) - models := make([]TestModel, 0) - err = repo.Query(context.Background(), qb, &models) + models, err := repo.Query(context.Background(), qb) s.NoError(err) s.Equal(1, len(models), "expected 1 test model") - s.Equal(*model, models[0]) + s.Equal(model, models[0]) } func (s *DbRepoQueryTestSuite) TestCreateWrongModel() { envConfig := s.Env().Config() envLogger := s.Env().Logger() - repo, err := db_repo.New(envConfig, envLogger, db_repo.Settings{ + repo, err := db_repo.New[uint, *WrongTestModel](envConfig, envLogger, db_repo.Settings{ Metadata: TestModelMetadata, }) s.NoError(err) @@ -106,7 +105,7 @@ func (s *DbRepoQueryTestSuite) TestReadCorrectModel() { envConfig := s.Env().Config() envLogger := s.Env().Logger() - repo, err := db_repo.New(envConfig, envLogger, db_repo.Settings{ + repo, err := db_repo.New[uint, *TestModel](envConfig, envLogger, db_repo.Settings{ Metadata: TestModelMetadata, }) s.NoError(err) @@ -118,9 +117,7 @@ func (s *DbRepoQueryTestSuite) TestReadCorrectModel() { err = repo.Create(context.Background(), model) s.NoError(err) - readModel := &TestModel{} - - err = repo.Read(context.Background(), model.GetId(), readModel) + readModel, err := repo.Read(context.Background(), *model.GetId()) s.NoError(err) s.Equal(*model, *readModel, "expected db model to match") } @@ -129,14 +126,12 @@ func (s *DbRepoQueryTestSuite) TestReadWrongModel() { envConfig := s.Env().Config() envLogger := s.Env().Logger() - repo, err := db_repo.New(envConfig, envLogger, db_repo.Settings{ + repo, err := db_repo.New[uint, *WrongTestModel](envConfig, envLogger, db_repo.Settings{ Metadata: TestModelMetadata, }) s.NoError(err) - model := &WrongTestModel{} - - err = repo.Read(context.Background(), mdl.Box(uint(1)), model) + _, err = repo.Read(context.Background(), 1) s.EqualError(err, "cross reading wrong model from repo") } @@ -144,7 +139,7 @@ func (s *DbRepoQueryTestSuite) TestUpdateCorrectModel() { envConfig := s.Env().Config() envLogger := s.Env().Logger() - repo, err := db_repo.New(envConfig, envLogger, db_repo.Settings{ + repo, err := db_repo.New[uint, *TestModel](envConfig, envLogger, db_repo.Settings{ Metadata: TestModelMetadata, }) s.NoError(err) @@ -163,11 +158,10 @@ func (s *DbRepoQueryTestSuite) TestUpdateCorrectModel() { qb := db_repo.NewQueryBuilder() qb.Where(where) - models := make([]TestModel, 0) - err = repo.Query(context.Background(), qb, &models) + models, err := repo.Query(context.Background(), qb) s.NoError(err) s.Equal(1, len(models), "expected 1 test model") - s.Equal(*model, models[0]) + s.Equal(model, models[0]) model.Name = mdl.Box("nameUpdate1Updated") @@ -181,18 +175,17 @@ func (s *DbRepoQueryTestSuite) TestUpdateCorrectModel() { qb = db_repo.NewQueryBuilder() qb.Where(where) - models = make([]TestModel, 0) - err = repo.Query(context.Background(), qb, &models) + models, err = repo.Query(context.Background(), qb) s.NoError(err) s.Equal(1, len(models), "expected 1 test model") - s.Equal(*model, models[0]) + s.Equal(model, models[0]) } func (s *DbRepoQueryTestSuite) TestUpdateWrongModel() { envConfig := s.Env().Config() envLogger := s.Env().Logger() - repo, err := db_repo.New(envConfig, envLogger, db_repo.Settings{ + repo, err := db_repo.New[uint, *WrongTestModel](envConfig, envLogger, db_repo.Settings{ Metadata: TestModelMetadata, }) s.NoError(err) @@ -209,7 +202,7 @@ func (s *DbRepoQueryTestSuite) TestDeleteCorrectModel() { envConfig := s.Env().Config() envLogger := s.Env().Logger() - repo, err := db_repo.New(envConfig, envLogger, db_repo.Settings{ + repo, err := db_repo.New[uint, *TestModel](envConfig, envLogger, db_repo.Settings{ Metadata: TestModelMetadata, }) s.NoError(err) @@ -229,7 +222,7 @@ func (s *DbRepoQueryTestSuite) TestDeleteWrongModel() { envConfig := s.Env().Config() envLogger := s.Env().Logger() - repo, err := db_repo.New(envConfig, envLogger, db_repo.Settings{ + repo, err := db_repo.New[uint, *WrongTestModel](envConfig, envLogger, db_repo.Settings{ Metadata: TestModelMetadata, }) s.NoError(err) @@ -246,7 +239,7 @@ func (s *DbRepoQueryTestSuite) TestQueryCorrectModel() { envConfig := s.Env().Config() envLogger := s.Env().Logger() - repo, err := db_repo.New(envConfig, envLogger, db_repo.Settings{ + repo, err := db_repo.New[uint, *TestModel](envConfig, envLogger, db_repo.Settings{ Metadata: TestModelMetadata, }) s.NoError(err) @@ -272,8 +265,7 @@ func (s *DbRepoQueryTestSuite) TestQueryCorrectModel() { qb := db_repo.NewQueryBuilder() qb.Where(where) - models := make([]TestModel, 0) - err = repo.Query(context.Background(), qb, &models) + models, err := repo.Query(context.Background(), qb) s.NoError(err) s.Equal(1, len(models), "expected 1 test model") s.Equal(where.Name, models[0].Name) @@ -283,57 +275,17 @@ func (s *DbRepoQueryTestSuite) TestQueryCorrectModel() { qb = db_repo.NewQueryBuilder() qb.Where(whereStr, mdl.Box("name2")) - models = make([]TestModel, 0) - err = repo.Query(context.Background(), qb, &models) + models, err = repo.Query(context.Background(), qb) s.NoError(err) s.Equal(1, len(models), "expected 1 test model") - s.Equal(*model, models[0]) -} - -func (s *DbRepoQueryTestSuite) TestQueryWrongResultModel() { - envConfig := s.Env().Config() - envLogger := s.Env().Logger() - - repo, err := db_repo.New(envConfig, envLogger, db_repo.Settings{ - Metadata: TestModelMetadata, - }) - s.NoError(err) - - model := &TestModel{ - Name: mdl.Box("name3"), - } - - err = repo.Create(context.Background(), model) - s.NoError(err) - - model = &TestModel{ - Name: mdl.Box("name4"), - } - - err = repo.Create(context.Background(), model) - s.NoError(err) - - where := &TestModel{ - Name: mdl.Box("name3"), - } - - qb := db_repo.NewQueryBuilder() - qb.Where(where) - - models := make([]WrongTestModel, 0) - - err = repo.Query(context.Background(), qb, models) - s.EqualError(err, "result slice has to be pointer to slice") - - err = repo.Query(context.Background(), qb, &models) - s.EqualError(err, "cross querying result slice has to be of same model") + s.Equal(model, models[0]) } func (s *DbRepoQueryTestSuite) TestQueryWrongModel() { envConfig := s.Env().Config() envLogger := s.Env().Logger() - repo, err := db_repo.New(envConfig, envLogger, db_repo.Settings{ + repo, err := db_repo.New[uint, *TestModel](envConfig, envLogger, db_repo.Settings{ Metadata: TestModelMetadata, }) s.NoError(err) @@ -345,8 +297,7 @@ func (s *DbRepoQueryTestSuite) TestQueryWrongModel() { qb := db_repo.NewQueryBuilder() qb.Where(where) - models := make([]TestModel, 0) - err = repo.Query(context.Background(), qb, &models) + _, err = repo.Query(context.Background(), qb) s.EqualError(err, "cross querying wrong model from repo") whereStruct := WrongTestModel{ @@ -356,8 +307,7 @@ func (s *DbRepoQueryTestSuite) TestQueryWrongModel() { qb = db_repo.NewQueryBuilder() qb.Where(whereStruct) - models = make([]TestModel, 0) - err = repo.Query(context.Background(), qb, &models) + _, err = repo.Query(context.Background(), qb) s.EqualError(err, "cross querying wrong model from repo") }