Documentation previewThese docs are actively being built. Some pages may change as the framework and examples are finalized.
Skip to content

Wiring Recipes

Use this page when you created a Go package and need to connect its constructors to an app.

GoForj apps use explicit provider sets. Your package owns constructors. The app's wire package imports those constructors and adds them to the right set.

Quick Map

You builtRegister it inTypical provider
Application serviceapp/wire/inject_services_app.gobilling.NewService
Outbound adapter or gatewayapp/wire/inject_services_app.gobilling.ProvideGateway
Repositoryapp/wire/inject_repositories_app.go when presentreports.NewRepository
HTTP controllerapp/wire/inject_http_controllers_app.gousers.NewController
App commandapp/wire/inject_cmd_app.go and app/commands.goreports.NewReconcileCommand
Job handlerapp/wire/inject_jobs_app.go when jobs are enabledreports.NewGenerateHandler
Scheduleapp/wire/inject_schedules_app.go and app/schedules.goreports.NewDailySchedule
Event subscriberapp/wire/inject_subscribers_app.gobilling.NewInvoicePaidSubscriber
Named resource adapterUsually app/wire/inject_services_app.goprovideUploadsDisk

For a named app, replace app/... with app/<name>/....

Use the most specific generated set that owns the surface. If a generated file is not present, the app probably does not have that component enabled.

Make Commands

For controllers and commands, start with the make command.

The make command is not just a file generator. It also injects the generated resource into the active app's wiring harness. Generate first, then review what changed.

FlowStart withVerify
HTTP controllerforj make:controller Userscontroller file, HTTP controller set, route registry
App commandforj make:command reports:reconcilecommand type, command Wire set, command collection
Queue jobforj make:job GenerateReportjob type, job Wire set
Scheduled taskforj make:schedule reports:daily --every 24hschedule type, schedule Wire set, schedule registration
Model repositoryforj make:model users --package usersmodel, repository, repository Wire set

Run the same flow through a named app when that app owns the resource:

bash
forj marketplace make:controller checkout
forj marketplace make:command catalog:rebuild

The wiring still matters because generated resources usually depend on application services. The make command wires the generated resource itself; you may still need to wire the application services it depends on.

See Make Commands for grouped package placement, output overrides, and the full command map.

Service and Adapter

Application packages usually own the service and any adapter it depends on:

text
internal/billing/gateway.go
internal/billing/provider.go
internal/billing/service.go
app/wire/inject_services_app.go

Then wire those constructors from:

text
app/wire/inject_services_app.go
go
package wire

import (
	"github.com/google/wire"

	"myapp/internal/billing"
)

var appServiceSet = wire.NewSet(
	// existing app providers...
	billing.ProvideGateway,
	billing.NewService,
)

Wire can construct *billing.Service because billing.ProvideGateway provides the *billing.Gateway that billing.NewService receives.

HTTP Controller

Controllers belong to the HTTP controller set:

bash
forj make:controller Users

After running the make command, verify the wiring it updated:

  • internal/users/controller.go exists
  • users.NewController is in app/wire/inject_http_controllers_app.go
  • the controller routes are included from app/routes.go

The controller can depend on an application service already provided by the app service set. If Wire cannot provide that service, add the service constructor to app/wire/inject_services_app.go.

Verify the result:

bash
forj build
forj route:list

Command

Application commands are registered from:

bash
forj make:command reports:reconcile

After running the make command, verify the wiring it updated:

  • the command type has Signature, constructor, and Run
  • the constructor is in app/wire/inject_cmd_app.go
  • the command is exposed through app/commands.go

Command constructors should receive application services as parameters. They should not create repositories, managers, clients, or services themselves.

Commands also need to be exposed through the generated command collection. See Commands for the command-specific registration path.

Named Resource

Named resources often need a small provider function that selects one generated resource from a manager:

go
package wire

import (
	"github.com/goforj/storage"

	"myapp/internal/storages"
	"myapp/internal/uploads"
)

var appServiceSet = wire.NewSet(
	// existing app providers...
	provideUploadsDisk,
	uploads.NewService,
)

func provideUploadsDisk(manager *storages.Manager) storage.Storage {
	return manager.Uploads()
}

The service receives the specific resource it needs instead of reaching into the manager itself.

After Editing

Regenerate the graph after changing providers or generated component files:

bash
forj build

forj build refreshes generated code, runs Wire, indexes APIs, and builds the app binary.

Common Mistakes

Common mistakes

  • Do not add constructors to app/wire/wire_gen.go; it is generated output.
  • Do not register a controller in the service set when it belongs in the HTTP controller set.
  • Do not create dependencies inside commands or controllers when they should be constructor parameters.
  • Do not use package globals to avoid wiring a provider.
  • Do not register two providers for the same raw type when domain-specific adapter types would make the graph clearer.

Next Steps