vandor sync
Regenerate wiring code for your Vandor project
vandor sync
Regenerate the wiring code that connects your bounded contexts, domains, use cases, and services together.
Synopsis
vandor sync <scope> [flags]Description
The sync command scans your project's filesystem to discover what components exist (contexts, domains, use cases, services) and then regenerates the *_gen.go wiring files that tie everything together. Think of it as the glue that keeps your FX module graph in sync with your actual code.
You do not normally need to run sync manually after using vandor add, because add triggers sync automatically. However, you will want to run it when you:
- Manually create or move files
- Delete components by hand
- Want to verify that generated code is up to date (especially in CI)
Generated files are safe to regenerate. Files ending in _gen.go (like module_gen.go, contexts_gen.go, modules_gen.go) are fully managed by sync and will be overwritten on every run. Your hand-written files (like module.go) are never touched by sync.
Three Scopes
Sync operates at three levels, from narrow to broad:
vandor sync context
Refresh the wiring for a single bounded context. This regenerates the module_gen.go file inside that context's directory, which registers all discovered use cases and services with FX.
vandor sync context <name>What it does:
- Scans the context directory for use cases, services, and domains
- Regenerates
internal/context/<name>/module_gen.go
Example:
vandor sync context orderThis updates internal/context/order/module_gen.go to include any new use cases or services you added to the order context.
What module_gen.go looks like:
// Code generated by vandor sync. DO NOT EDIT.
package order
import (
"go.uber.org/fx"
"project/internal/context/order/usecase"
"project/internal/context/order/core/service"
)
var GeneratedModule = fx.Module("order-gen",
fx.Provide(
usecase.NewCreateOrder,
usecase.NewCancelOrder,
usecase.NewGetOrderByID,
),
fx.Provide(
service.NewPriceCalculator,
),
)Meanwhile, your hand-written module.go composes GeneratedModule with any custom wiring you need, and sync will never overwrite it.
vandor sync core
Refresh the aggregate wiring files that live in internal/core/. These files pull all your individual context modules together into a single module graph.
vandor sync coreWhat it does:
- Scans all contexts in
internal/context/ - Regenerates
internal/core/contexts_gen.go(lists all context modules) - Regenerates
internal/core/modules_gen.go(aggregates everything)
What contexts_gen.go looks like:
// Code generated by vandor sync. DO NOT EDIT.
package core
import (
"go.uber.org/fx"
"project/internal/context/order"
"project/internal/context/identity"
"project/internal/context/catalog"
)
var ContextModules = fx.Options(
order.Module,
identity.Module,
catalog.Module,
)vandor sync all
Run context sync for every context, then run core sync. This is the most thorough option and ensures everything is consistent.
vandor sync allWhat it does:
- Discovers all contexts in
internal/context/ - Runs
sync contextfor each one (regenerating eachmodule_gen.go) - Runs
sync core(regeneratingcontexts_gen.goandmodules_gen.go)
This is the command you want when you are not sure what changed, or when you want to make sure everything is fully up to date.
Flags
--check CI mode: check if generated code is stale without modifying files.
Exits with non-zero status if any _gen.go file would change.
--tidy auto|always|never When to run go mod tidy (default: auto)The --check Flag (CI Mode)
The --check flag is designed for continuous integration pipelines. Instead of regenerating files, it checks whether the current _gen.go files match what sync would produce. If there is a mismatch, it exits with a non-zero code.
# In your CI pipeline
vandor sync all --checkIf the check fails, it means someone added or removed components without running sync. The CI output will tell you which files are stale:
STALE: internal/context/order/module_gen.go
STALE: internal/core/contexts_gen.go
Generated code is out of date. Run 'vandor sync all' to fix.
Exit code: 1This is a great guard to add to your CI pipeline to catch forgotten syncs before they reach production.
Example CI step (GitHub Actions):
- name: Check generated code
run: vandor sync all --checkHow Sync Discovers Components
Sync does not maintain a manifest or database of your components. Instead, it reads directly from the filesystem:
- Contexts are discovered by scanning
internal/context/for directories that contain amodule.gofile. - Use cases are discovered by scanning each context's
usecase/directory for Go files withNew*constructor functions. - Services are discovered by scanning each context's
core/service/directory for Go files withNew*constructor functions. - Domains are discovered by scanning each context's
core/domain/directory.
This means you can create components manually (without vandor add) and sync will pick them up, as long as they follow the expected directory structure and naming conventions.
Which Files Does Sync Touch?
Sync only writes to files that end in _gen.go:
| File | Scope | Purpose |
|---|---|---|
internal/context/<ctx>/module_gen.go | sync context | Wire use cases and services in one context |
internal/core/contexts_gen.go | sync core | List all context modules |
internal/core/modules_gen.go | sync core | Aggregate module graph |
Files that sync never touches:
module.go(your hand-written module composition)- Any use case, service, or domain files
- Configuration files
- Test files
Do not manually edit _gen.go files. They are overwritten every time sync runs. If you need custom wiring, put it in the non-generated module.go file in each context.
Examples
Sync everything after manual changes
# You manually created some files, now sync to pick them up
vandor sync allSync a single context after adding a use case
vandor sync context orderCI pipeline check
# Fail the build if generated code is stale
vandor sync all --checkSync all, skip go mod tidy
vandor sync all --tidy neverWhen Do You Need to Sync Manually?
Most of the time, you do not. The vandor add command triggers sync automatically. But here are cases where manual sync is needed:
- You created files by hand -- For example, you wrote a new use case file directly instead of using
vandor add usecase. - You deleted files by hand -- If you removed a use case or service file, sync needs to update the generated wiring to remove the reference.
- You renamed files -- Moving or renaming Go files requires a sync to update imports.
- CI verification -- Use
--checkin CI to verify nothing is stale.
Troubleshooting
Import errors after sync
If you see import errors after syncing:
go mod tidy
vandor sync allSync does not detect my new use case
Make sure your use case follows the expected pattern:
- It is in the
usecase/directory of the context - It has a
New*constructor function - The file compiles without errors
# Check that the file is valid Go
go vet ./internal/context/order/usecase/...Generated file has wrong imports
Force a full re-sync:
vandor sync all --tidy alwaysRelated Commands
- vandor add - Add components (auto-triggers sync)
- vandor vpkg - Manage infrastructure packages
- vandor new - Create a new project