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.goreports.NewDailySchedule and its AppSchedules entry
Event subscriberapp/wire/inject_subscribers_app.gobilling.NewInvoicePaidSubscriber
Named resource adapterUsually app/wire/inject_services_app.goprovideUploadsDisk

For an additional app, replace app/... with the owning app's 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.

Generated Resources

When a resource has a make command, use it before editing provider sets by hand. The command creates the resource and updates the active App's generated wiring boundaries.

The Make Command Reference shows each generator in the same Usage / Files touched / Generated code format. This page begins where those flows stop: wiring the application services and adapters that generated entry points depend on.

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/goforj/wire"

	"myapp/internal/billing"
)

var appSet = 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

The controller verification workflow shows the command, files, and injected route registration together.

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

The command creation workflow shows the command, generated type, provider, and App command collection together.

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 appSet = 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