{"id":21951878,"url":"https://github.com/go-coldbrew/data-builder","last_synced_at":"2026-04-04T11:05:28.066Z","repository":{"id":44565235,"uuid":"455846651","full_name":"go-coldbrew/data-builder","owner":"go-coldbrew","description":"Dependency injection framework that compiles builder functions into an execution plan with automatic dependency resolution and parallel execution","archived":false,"fork":false,"pushed_at":"2026-04-01T13:50:39.000Z","size":321,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-02T04:55:25.718Z","etag":null,"topics":["coldbrew","dag","databuilder","dependency-injection","dependency-resolution","go","golang","parallel-execution"],"latest_commit_sha":null,"homepage":"https://docs.coldbrew.cloud","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/go-coldbrew.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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-02-05T11:07:07.000Z","updated_at":"2026-03-31T10:58:46.000Z","dependencies_parsed_at":"2024-06-21T11:53:13.911Z","dependency_job_id":"fea0a9e1-389d-4a91-a3ee-285cd00dc7df","html_url":"https://github.com/go-coldbrew/data-builder","commit_stats":null,"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"purl":"pkg:github/go-coldbrew/data-builder","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-coldbrew%2Fdata-builder","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-coldbrew%2Fdata-builder/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-coldbrew%2Fdata-builder/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-coldbrew%2Fdata-builder/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/go-coldbrew","download_url":"https://codeload.github.com/go-coldbrew/data-builder/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/go-coldbrew%2Fdata-builder/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31397056,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-04T10:20:44.708Z","status":"ssl_error","status_checked_at":"2026-04-04T10:20:06.846Z","response_time":60,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["coldbrew","dag","databuilder","dependency-injection","dependency-resolution","go","golang","parallel-execution"],"created_at":"2024-11-29T06:18:01.686Z","updated_at":"2026-04-04T11:05:28.042Z","avatar_url":"https://github.com/go-coldbrew.png","language":"Go","readme":"\u003c!-- Code generated by gomarkdoc. DO NOT EDIT --\u003e\n\n[![CI](https://github.com/go-coldbrew/data-builder/actions/workflows/go.yml/badge.svg)](https://github.com/go-coldbrew/data-builder/actions/workflows/go.yml)\n[![Go Report Card](https://goreportcard.com/badge/github.com/go-coldbrew/data-builder)](https://goreportcard.com/report/github.com/go-coldbrew/data-builder)\n[![GoDoc](https://pkg.go.dev/badge/github.com/go-coldbrew/data-builder.svg)](https://pkg.go.dev/github.com/go-coldbrew/data-builder)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\n\n\n# databuilder\n\n```go\nimport \"github.com/go-coldbrew/data-builder\"\n```\n\n## Index\n\n- [Constants](\u003c#constants\u003e)\n- [Variables](\u003c#variables\u003e)\n- [func AddResultToCtx\\(ctx context.Context, r Result\\) context.Context](\u003c#AddResultToCtx\u003e)\n- [func BuildGraph\\(executionPlan Plan, format, file string\\) error](\u003c#BuildGraph\u003e)\n- [func GetFromResult\\(ctx context.Context, obj any\\) any](\u003c#GetFromResult\u003e)\n- [func IsValidBuilder\\(builder any\\) error](\u003c#IsValidBuilder\u003e)\n- [func MaxPlanParallelism\\(pl Plan\\) \\(uint, error\\)](\u003c#MaxPlanParallelism\u003e)\n- [type DataBuilder](\u003c#DataBuilder\u003e)\n  - [func New\\(\\) DataBuilder](\u003c#New\u003e)\n- [type Plan](\u003c#Plan\u003e)\n- [type Result](\u003c#Result\u003e)\n  - [func GetResultFromCtx\\(ctx context.Context\\) Result](\u003c#GetResultFromCtx\u003e)\n  - [func \\(r Result\\) Get\\(obj any\\) any](\u003c#Result.Get\u003e)\n\n\n## Constants\n\n\u003ca name=\"SupportPackageIsVersion1\"\u003e\u003c/a\u003eSupportPackageIsVersion1 is a compile\\-time assertion constant. Downstream packages reference this to enforce version compatibility.\n\n```go\nconst SupportPackageIsVersion1 = true\n```\n\n## Variables\n\n\u003ca name=\"ErrInvalidBuilder\"\u003e\u003c/a\u003e\n\n```go\nvar (\n    // ErrInvalidBuilder is returned when the builder is not valid\n    ErrInvalidBuilder = errors.New(\"the provided builder is invalid\")\n    // ErrInvalidBuilderKind is returned when the builder is not a function\n    ErrInvalidBuilderKind = errors.New(\"invalid builder, should only be a function\")\n    // ErrInvalidBuilderNumInput is returned when the builder does not have 1 input\n    ErrInvalidBuilderNumOutput = errors.New(\"invalid builder, should always return two values\")\n    // ErrInvalidBuilderFirstOutput is returned when the builder does not return a struct as first output\n    ErrInvalidBuilderFirstOutput = errors.New(\"invalid builder, first return type should be a struct\")\n    // ErrInvalidBuilderSecondOutput is returned when the builder does not return an error as second output\n    ErrInvalidBuilderSecondOutput = errors.New(\"invalid builder, second return type should be error\")\n    // ErrInvalidBuilderMissingContext is returned when the builder does not have a context as first input\n    ErrInvalidBuilderMissingContext = errors.New(\"invalid builder, missing context\")\n    // ErrInvalidBuilderInput is returned when the builder does not have a struct as input\n    ErrInvalidBuilderInput = errors.New(\"invalid builder, input should be a struct\")\n    // ErrInvalidBuilderOutput is returned when the builder does not have a struct as output\n    ErrMultipleBuilderSameOutput = errors.New(\"invalid, multiple builders CAN NOT produce the same output\")\n    // ErrSameInputAsOutput is returned when the builder has the same input and output\n    ErrSameInputAsOutput = errors.New(\"invalid builder, input and output should NOT be same\")\n    // ErrCouldNotResolveDependency is returned when the builder can not be resolved\n    ErrCouldNotResolveDependency = errors.New(\"dependency can not be resolved\")\n    // ErrMultipleInitialData is returned when the initial data is provided twice\n    ErrMultipleInitialData = errors.New(\"initial data provided twice\")\n    // ErrInitialDataMissing is returned when the initial data is not provided\n    ErrInitialDataMissing = errors.New(\"need complile time defined initial data to run\")\n)\n```\n\n\u003ca name=\"ErrWTF\"\u003e\u003c/a\u003eErrWTF is the error returned in case we find dependency resolution related errors, please report this\n\n```go\nvar ErrWTF = errors.New(\"what a terrible failure: this is likely a bug in dependency resolution, please report this\")\n```\n\n\u003ca name=\"AddResultToCtx\"\u003e\u003c/a\u003e\n## func [AddResultToCtx](\u003chttps://github.com/go-coldbrew/data-builder/blob/main/context.go#L17\u003e)\n\n```go\nfunc AddResultToCtx(ctx context.Context, r Result) context.Context\n```\n\nAddResultToCtx adds the given result object to context\n\nthis function should ideally only be used in your tests and/or for debugging modification made to Result obj will NOT persist\n\n\u003ca name=\"BuildGraph\"\u003e\u003c/a\u003e\n## func [BuildGraph](\u003chttps://github.com/go-coldbrew/data-builder/blob/main/plan.go#L319\u003e)\n\n```go\nfunc BuildGraph(executionPlan Plan, format, file string) error\n```\n\nBuildGraph helps understand the execution plan, it renders the plan in the given format please note we depend on graphviz, please ensure you have graphviz installed\n\n\u003ca name=\"GetFromResult\"\u003e\u003c/a\u003e\n## func [GetFromResult](\u003chttps://github.com/go-coldbrew/data-builder/blob/main/context.go#L44\u003e)\n\n```go\nfunc GetFromResult(ctx context.Context, obj any) any\n```\n\nGetFromResult allows builders to access data built by other builders\n\nthis function enables optional access to data, your code should not rely on values being present, if you have explicit dependency please add them to your function parameters\n\n\u003ca name=\"IsValidBuilder\"\u003e\u003c/a\u003e\n## func [IsValidBuilder](\u003chttps://github.com/go-coldbrew/data-builder/blob/main/databuilder.go#L94\u003e)\n\n```go\nfunc IsValidBuilder(builder any) error\n```\n\nIsValidBuilder checks if the given function is valid or not\n\n\u003ca name=\"MaxPlanParallelism\"\u003e\u003c/a\u003e\n## func [MaxPlanParallelism](\u003chttps://github.com/go-coldbrew/data-builder/blob/main/plan.go#L331\u003e)\n\n```go\nfunc MaxPlanParallelism(pl Plan) (uint, error)\n```\n\nMaxPlanParallelism return the maximum number of buildes that can be exsecuted parallely for a given plan\n\nthis number does not take into account if the builder are cpu intensive or netwrok intensive it may not be benificial to run builders at max parallelism if they are cpu intensive\n\n\u003ca name=\"DataBuilder\"\u003e\u003c/a\u003e\n## type [DataBuilder](\u003chttps://github.com/go-coldbrew/data-builder/blob/main/types.go#L36-L42\u003e)\n\nDataBuilder is the interface for DataBuilder\n\n```go\ntype DataBuilder interface {\n    // AddBuilders adds the builders to the DataBuilder. The builders are added to the DataBuilder\n    AddBuilders(fn ...any) error\n    // Compile compiles the builders and returns a plan that can be used to run the builders\n    // The initial data is used to resolve the dependencies of the builders. The initial data should be a struct that contains the fields that are used as input for the builders when this Plan is executed.\n    Compile(initialData ...any) (Plan, error)\n}\n```\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\n\u003cp\u003e\n\n\n\n```go\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"strings\"\n)\n\n// lets say we have some data being produced by a set of functions\n// but we need to define how their interaction should be and how their dependency\n// should be resolved\n\ntype AppRequest struct {\n\tFirstName string\n\tCityName  string\n\tUpperCase bool\n\tLowerCase bool\n}\n\ntype AppResponse struct {\n\tMsg string\n}\n\ntype NameMsg struct {\n\tMsg string\n}\n\ntype CityMsg struct {\n\tMsg string\n}\n\ntype CaseMsg struct {\n\tMsg string\n}\n\n// Lets try to build a sample builder with some dependency\n// Assuming we have an App that acts on the request\n// processes it in multiple steps and returns a Response\n// we can think of this process as a series of functions\n\n// NameMsgBuilder builds name salutation from our AppRequest\nfunc NameMsgBuilder(_ context.Context, req AppRequest) (NameMsg, error) {\n\treturn NameMsg{\n\t\tMsg: fmt.Sprintf(\"Hello %s!\", req.FirstName),\n\t}, nil\n}\n\n// CityMsgBuilder builds city welcome msg from our AppRequest\nfunc CityMsgBuilder(_ context.Context, req AppRequest) (CityMsg, error) {\n\treturn CityMsg{\n\t\tMsg: fmt.Sprintf(\"Welcome to %s\", req.CityName),\n\t}, nil\n}\n\n// CaseMsgBuilder handles the case transformation of the message\nfunc CaseMsgBuilder(_ context.Context, name NameMsg, city CityMsg, req AppRequest) (CaseMsg, error) {\n\tmsg := fmt.Sprintf(\"%s\\n%s\", name.Msg, city.Msg)\n\tif req.UpperCase {\n\t\tmsg = strings.ToUpper(msg)\n\t} else if req.LowerCase {\n\t\tmsg = strings.ToLower(msg)\n\t}\n\treturn CaseMsg{\n\t\tMsg: msg,\n\t}, nil\n}\n\n// ResponseBuilder builds Application response from CaseMsg\nfunc ResponseBuilder(_ context.Context, m CaseMsg) (AppResponse, error) {\n\treturn AppResponse{\n\t\tMsg: m.Msg,\n\t}, nil\n}\n\nfunc main() {\n\t// First we build an object of the builder interface\n\tb := New()\n\n\t// Then we add all the builders\n\t// its okay to call `AddBuilders` multiple times\n\terr := b.AddBuilders(\n\t\tNameMsgBuilder,\n\t\tCityMsgBuilder,\n\t\tCaseMsgBuilder,\n\t)\n\tfmt.Println(err == nil)\n\n\t// lets ass all builders\n\terr = b.AddBuilders(ResponseBuilder)\n\tfmt.Println(err == nil)\n\n\t// next we we compile this into a plan\n\t// the compilation ensures we have a resolved dependency graph\n\t_, err = b.Compile()\n\tfmt.Println(err != nil)\n\n\t// Why did we get the error ?\n\t// if we look at our dependency graph, there is no builder that produces AppRequest\n\t// in order of dependency resolution to work we need to tell\n\t// the Compile method that we will provide it some initial Data\n\n\t// we can do that by passing empty structs\n\t// compiler just needs the type, values will come in later\n\tep, err := b.Compile(AppRequest{})\n\tfmt.Println(err == nil)\n\n\t// once the Compilation has finished, we get an execution plan\n\t// the execution plan once created can be cached and is side effect free\n\t// It can be executed across multiple go routines\n\t// lets run the Plan, remember to pass in the initial value\n\tresult, err := ep.Run(\n\t\tcontext.Background(), // context is passed on the builders\n\t\tAppRequest{\n\t\t\tFirstName: \"Ankur\",\n\t\t\tCityName:  \"Singapore\",\n\t\t\tLowerCase: true,\n\t\t},\n\t)\n\tfmt.Println(err == nil)\n\n\t// once the execution is done, we can read all the values from the result\n\tresp := AppResponse{}\n\tresp = result.Get(resp).(AppResponse)\n\tfmt.Println(resp.Msg)\n\n}\n```\n\n#### Output\n\n```\ntrue\ntrue\ntrue\ntrue\ntrue\nhello ankur!\nwelcome to singapore\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n\u003ca name=\"New\"\u003e\u003c/a\u003e\n### func [New](\u003chttps://github.com/go-coldbrew/data-builder/blob/main/databuilder.go#L178\u003e)\n\n```go\nfunc New() DataBuilder\n```\n\nNew Creates a new DataBuilder\n\n\u003ca name=\"Plan\"\u003e\u003c/a\u003e\n## type [Plan](\u003chttps://github.com/go-coldbrew/data-builder/blob/main/types.go#L45-L52\u003e)\n\nPlan is the interface that wraps execution of Plans created by DataBuilder.Compile method.\n\n```go\ntype Plan interface {\n    // Replace replaces the builder function used in compile with a different function. The builder function should be the same as the one used in AddBuilders\n    Replace(ctx context.Context, from, to any) error\n    // Run runs the builders in the plan. The initial data is used to resolve the dependencies of the builders. The initial data should be a struct that contains the fields that are used as input for the builders when this Plan is executed.\n    Run(ctx context.Context, initValues ...any) (Result, error)\n    // RunParallel runs the builders in the plan in parallel. The initial data is used to resolve the dependencies of the builders. The initial data should be a struct that contains the fields that are used as input for the builders when this Plan is executed.\n    RunParallel(ctx context.Context, count uint, initValues ...any) (Result, error)\n}\n```\n\n\u003cdetails\u003e\u003csummary\u003eExample\u003c/summary\u003e\n\u003cp\u003e\n\n\n\n```go\nb := New()\nerr := b.AddBuilders(DBTestFunc, DBTestFunc4)\nfmt.Println(err == nil)\nep, err := b.Compile(TestStruct1{})\nfmt.Println(err == nil)\n\n_, err = ep.Run(context.Background(), TestStruct1{})\nfmt.Println(err == nil)\n\nerr = ep.Replace(context.Background(), DBTestFunc, DBTestFunc5)\nfmt.Println(err == nil)\n_, err = ep.Run(context.Background(), TestStruct1{})\nfmt.Println(err == nil)\n\n// Output:\n// true\n// true\n// CALLED DBTestFunc\n// CALLED DBTestFunc4\n// true\n// true\n// CALLED DBTestFunc5\n// CALLED DBTestFunc4\n// true\n```\n\n#### Output\n\n```\ntrue\ntrue\nCALLED DBTestFunc\nCALLED DBTestFunc4\ntrue\ntrue\nCALLED DBTestFunc5\nCALLED DBTestFunc4\ntrue\n```\n\n\u003c/p\u003e\n\u003c/details\u003e\n\n\u003ca name=\"Result\"\u003e\u003c/a\u003e\n## type [Result](\u003chttps://github.com/go-coldbrew/data-builder/blob/main/types.go#L55\u003e)\n\nResult is the result of the Plan.Run method\n\n```go\ntype Result map[string]any\n```\n\n\u003ca name=\"GetResultFromCtx\"\u003e\u003c/a\u003e\n### func [GetResultFromCtx](\u003chttps://github.com/go-coldbrew/data-builder/blob/main/context.go#L28\u003e)\n\n```go\nfunc GetResultFromCtx(ctx context.Context) Result\n```\n\nGetResultFromCtx gives access to result object at this point in execution\n\nthis function should ideally only be used in your tests and/or for debugging modification made to Result obj may or may not persist\n\n\u003ca name=\"Result.Get\"\u003e\u003c/a\u003e\n### func \\(Result\\) [Get](\u003chttps://github.com/go-coldbrew/data-builder/blob/main/plan.go#L247\u003e)\n\n```go\nfunc (r Result) Get(obj any) any\n```\n\nResult.Get returns the value of the struct from the result if the struct is not found in the result, nil is returned\n\nGenerated by [gomarkdoc](\u003chttps://github.com/princjef/gomarkdoc\u003e)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgo-coldbrew%2Fdata-builder","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgo-coldbrew%2Fdata-builder","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgo-coldbrew%2Fdata-builder/lists"}