{"id":17131237,"url":"https://github.com/phramz/dimple","last_synced_at":"2025-09-10T05:11:18.932Z","repository":{"id":64298189,"uuid":"553051497","full_name":"phramz/dimple","owner":"phramz","description":"Lightweight dependency injection container library for Golang","archived":false,"fork":false,"pushed_at":"2024-11-25T05:44:54.000Z","size":54,"stargazers_count":1,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-04T17:57:51.117Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/phramz.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-10-17T16:30:19.000Z","updated_at":"2024-05-29T12:40:42.000Z","dependencies_parsed_at":"2023-12-18T13:46:16.706Z","dependency_job_id":"db9a7a07-f656-42e4-b50b-f8f59e88b742","html_url":"https://github.com/phramz/dimple","commit_stats":null,"previous_names":[],"tags_count":42,"template":false,"template_full_name":null,"purl":"pkg:github/phramz/dimple","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phramz%2Fdimple","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phramz%2Fdimple/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phramz%2Fdimple/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phramz%2Fdimple/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/phramz","download_url":"https://codeload.github.com/phramz/dimple/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phramz%2Fdimple/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":274416208,"owners_count":25280912,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-10T02:00:12.551Z","response_time":83,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-14T19:14:22.197Z","updated_at":"2025-09-10T05:11:18.861Z","avatar_url":"https://github.com/phramz.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"Dimple (DI)\n===========\n\nLightweight dependency injection container library for Golang inspired by [Pimple](https://github.com/silexphp/Pimple).\n\n## Install\n\n```shell\ngo get github.com/phramz/dimple\n```\n## Usage\n\nHere a very basic example how it works in general:\n```go\nfunc main() {\n\t// Builder() returns an instance of ContainerBuilder to configure the container\n\tbuilder := dimple.Builder(\n\t\t// let's add our favorite time format as parameter to the container so other\n\t\t// services can pick it up\n\t\tdimple.Param(\"config.time_format\", time.Kitchen),\n\n\t\t// we can just add an anonymous function as factory for our \"logger\" service since it does not\n\t\t// depend on other services\n\t\t// and therefore does not need any context\n\t\tdimple.Service(\"logger\", dimple.WithFn(func() any {\n\t\t\tlogger := logrus.New()\n\t\t\tlogger.SetOutput(os.Stdout)\n\n\t\t\treturn logger\n\t\t})),\n\n\t\t// this service depends on the \"logger\" to output the time and \"config.time_format\" for the\n\t\t// desired format.\n\t\t// that is why we need to use WithContextFn to get to the container and context\n\t\tdimple.Service(\"service.time\", dimple.WithContextFn(func(ctx dimple.FactoryCtx) (any, error) {\n\t\t\t// you get can whatever dependency you need from the container as\n\t\t\t// long as you do not create a circular dependency\n\t\t\tlogger := ctx.Container().MustGet(\"logger\").(*logrus.Logger)\n\t\t\tformat := ctx.Container().MustGet(\"config.time_format\").(string)\n\n\t\t\treturn \u0026TimeService{\n\t\t\t\tlogger: logger.WithField(\"service\", ctx.ServiceID()),\n\t\t\t\tformat: format,\n\t\t\t}, nil\n\t\t})),\n\t)\n\n\t// once we're done building we can retrieve a new instance of Container\n\tcontainer, err := builder.Build(context.Background())\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\t// this is optional, but recommend since it will instantiate all service eager and\n\t// would return an error if there are issues. We don't want it to panic during runtime but\n\t// rather error on startup\n\tif err = container.Boot(); err != nil {\n\t\tpanic(err)\n\t}\n\n    // retrieve the *TimeService instance via generic function. Beware that illegal type assertions will panic\n    timeService := dimple.MustGetT[*TimeService](container, \"service.time\")\n    timeService.Now()\n}\n```\n\nFull example see [examples/basic/main.go](./examples/basic/main.go)\n\n### Tags\n\nIt is possible to annotate public struct members using the `inject` tag to get all necessary dependencies\nwithout explicitly registering a struct as service and the need of a factory function.\n\n```go\n\ntype TaggedTimeService struct {\n\tLogger *logrus.Logger `inject:\"logger\"`             // each tag point to the registered definition ID\n\tFormat string         `inject:\"config.time_format\"` // fields must be public for this to work!\n}\n\nfunc (t *TaggedTimeService) Now() {\n\tt.Logger.Infof(\"It is %s\", time.Now().Format(t.Format))\n}\n\nfunc main() {\n\tcontainer := dimple.Builder(\n\t\tdimple.Param(\"config.time_format\", time.Kitchen),\n\t\tdimple.Service(\"logger\", dimple.WithFn(func() any {\n\t\t\tl := logrus.New()\n\t\t\tl.SetLevel(logrus.DebugLevel)\n\t\t\treturn l\n\t\t})),\n\t\tdimple.Service(\"service.time\", dimple.WithInstance(\u0026TaggedTimeService{})),\n\t).\n\t\tMustBuild(context.Background())\n\n    timeService := dimple.MustGetT[*TaggedTimeService](container, \"service.time\")\n    logger := dimple.MustGetT[*logrus.Logger](container, \"logger\")\n\n    logger.Debug(\"timeService says ...\")\n    timeService.Now()\n\n    // if you want to inject services into struct which is not itself registered as a service\n    // you might do it using Inject()\n    anotherInstance := \u0026TaggedTimeService{}\n    if err := container.Inject(anotherInstance); err != nil {\n        panic(err)\n    }\n\n    logger.Debug(\"anotherInstance says ...\")\n    anotherInstance.Now()\n}\n```\nFull example see [examples/basic/main.go](./examples/basic/main.go)\n\n### Decorators\n\nDecorator can be used to wrap a service with another.\n\n```go\n\n// TimeServiceInterface it might be beneficial to have an interface for abstraction when it comes to service decoration\ntype TimeServiceInterface interface {\n\tNow()\n}\n\n// OriginTimeService is the service we want to decorate\ntype OriginTimeService struct {\n\tLogger *logrus.Logger `inject:\"logger\"`\n\tFormat string         `inject:\"config.time_format\"`\n}\n\nfunc (t *OriginTimeService) Now() {\n\tt.Logger.Infof(\"It is %s\", time.Now().Format(t.Format))\n}\n\n// TimeServiceDecorator will decorate OriginTimeService\ntype TimeServiceDecorator struct {\n\tLogger    *logrus.Logger `inject:\"logger\"`\n\tDecorated TimeServiceInterface\n}\n\nfunc (t *TimeServiceDecorator) Now() {\n\tt.Logger.Infof(\"%d seconds elapsed since January 1, 1970 UTC\", time.Now().Unix())\n\tt.Decorated.Now() // let's call the origin TaggedService as well\n}\n\nfunc main() {\n\tcontainer := dimple.Builder(\n\t\tdimple.Param(\"config.time_format\", time.Kitchen),\n\t\tdimple.Service(\"logger\", dimple.WithInstance(logrus.New())),\n\t\tdimple.Service(\"service.time\", dimple.WithInstance(\u0026OriginTimeService{})),\n\t\tdimple.Decorator(\"service.time.decorator\", \"service.time\", dimple.WithContextFn(func(ctx dimple.FactoryCtx) (any, error) {\n\t\t\treturn \u0026TimeServiceDecorator{\n\t\t\t\t// we can get the inner (origin) instance if we need to\n\t\t\t\tDecorated: ctx.Decorated().(TimeServiceInterface),\n\t\t\t}, nil\n\t\t})),\n\t).\n\t\tMustBuild(context.Background())\n\n    // now when we call MustGet() we will actually receive the TimeServiceDecorator\n\t// instead of OriginTimeService\n    timeService := dimple.MustGetT[TimeServiceInterface](container, \"service.time\")\n    timeService.Now()\n}\n```\n\nFull example see [examples/decorator/main.go](./examples/decorator/main.go)\n\n## Build-in services\n\n### Container\nYou can always get or inject the service container instance by addressing\nthe service-id `container` e.g.:\n\n```go\ntype ContainerAwareService struct {\n\tcontainer Container `inject:\"container\"`\n}\n```\n\n### Context\nYou can always get or inject the context given at Build() by addressing\nthe service-id `context` e.g.:\n\n```go\ntype ContextAwareService struct {\n\tctx context.Context `inject:\"context\"`\n}\n```\n\n## Credits\n\nThis library is based on various awesome open source libraries kudos going to:\n* https://github.com/silexphp/Pimple\n* https://github.com/thoas/go-funk\n* https://github.com/stretchr/testify\n\n## License\n\nThis project is licensed under MIT License. See [LICENSE](./LICENSE) file.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphramz%2Fdimple","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fphramz%2Fdimple","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphramz%2Fdimple/lists"}