cmdutil

package
v0.1.45 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 14, 2026 License: Apache-2.0 Imports: 13 Imported by: 0

Documentation

Overview

Package cmdutil holds cross-cutting helpers shared by forge's own CLI across MORE THAN ONE command group (internal/cli and its dir-nested subpackages). It is a leaf package — it imports only neutral internal packages — so any command group can depend on it without an import cycle back to internal/cli.

Helpers used by a single command stay with that command; trivial stdlib wrappers (a one-line os.Stat check) are duplicated locally rather than shared. Only genuinely shared logic lives here.

Index

Constants

This section is empty.

Variables

View Source
var ErrProjectConfigNotFound = errors.New("forge.yaml not found in current directory (run 'forge project new' to create a project)")

ErrProjectConfigNotFound is returned when forge.yaml does not exist. The canonical sentinel lives here (the shared leaf package) so both internal/cli and the dir-nested command groups compare against the same value; internal/cli's config.ErrProjectConfigNotFound aliases this.

View Source
var GoKeywords = map[string]bool{
	"break": true, "case": true, "chan": true, "const": true, "continue": true,
	"default": true, "defer": true, "else": true, "fallthrough": true, "for": true,
	"func": true, "go": true, "goto": true, "if": true, "import": true,
	"interface": true, "map": true, "package": true, "range": true, "return": true,
	"select": true, "struct": true, "switch": true, "type": true, "var": true,
}

GoKeywords is the set of Go reserved keywords.

View Source
var GoPredeclaredIdentifiers = map[string]bool{

	"bool": true, "byte": true, "complex64": true, "complex128": true,
	"error": true, "float32": true, "float64": true,
	"int": true, "int8": true, "int16": true, "int32": true, "int64": true,
	"rune": true, "string": true,
	"uint": true, "uint8": true, "uint16": true, "uint32": true, "uint64": true, "uintptr": true,
	"any": true, "comparable": true,

	"true": true, "false": true, "iota": true,

	"nil": true,

	"append": true, "cap": true, "close": true, "complex": true, "copy": true,
	"delete": true, "imag": true, "len": true, "make": true, "new": true,
	"panic": true, "print": true, "println": true, "real": true, "recover": true,
	"min": true, "max": true, "clear": true,
}

GoPredeclaredIdentifiers is the set of Go predeclared types, constants, zero value, and builtin functions.

View Source
var ReservedServiceNames = map[string]bool{
	"worker": true, "scheduler": true, "cron": true, "job": true,
}

ReservedServiceNames are names that conflict with forge's worker/scheduler subsystems. Using them as HTTP Connect service names causes confusion.

Functions

func CmdRouteTokens added in v0.1.45

func CmdRouteTokens() ([]string, bool)

CmdRouteTokens returns the recorded mount route (subcommand tokens from the executing binary to forge's root) and whether one was recorded this process.

func CountLineStartScaffoldMarkers

func CountLineStartScaffoldMarkers(data []byte) int

CountLineStartScaffoldMarkers counts line-start `// FORGE_SCAFFOLD:` and `# FORGE_SCAFFOLD:` markers in data. (The lint analyzer is Go-only, but audit/map are allowed to span more file types — hence both comment styles.)

func FindProjectRoot

func FindProjectRoot() (string, error)

FindProjectRoot walks upward from the resolution root (--project-dir when set, else the cwd) looking for a forge.yaml. Returns the directory or "" when no project is found. Mirrors the loadProjectConfig walk-up behavior in config.go.

func HideDevFlags

func HideDevFlags(cmd *cobra.Command, names ...string)

HideDevFlags is the user-vs-maintainer CLI surface split, shared by `forge generate` (internal/cli) and `forge lint` (internal/cli/lint).

Commands like `forge lint` and `forge generate` accumulate flags for two very different audiences: project users (the 5-7 flags they actually reach for) and forge maintainers / debugging agents (wiring audits, pipeline narrowing, migration escape hatches). Showing all of them in --help buries the user-facing surface. HideDevFlags marks the named flags Hidden — fully functional, just invisible in --help — and adds a visible --help-dev flag that lists exactly the hidden set, so the flags stay discoverable in one place.

Must be called after cmd.RunE and all flags are set. Panics on an unknown flag name: that's a programmer error at command-construction time, and panicking keeps a typo from silently leaving a dev flag visible.

It lives here in the shared leaf so the dir-nested lint group reaches it without importing internal/cli (which would cycle — internal/cli blank-imports the groups).

func IsMarkerScannable

func IsMarkerScannable(name string) bool

IsMarkerScannable identifies file types whose FORGE_SCAFFOLD markers are real unfilled placeholders rather than documentation references. Markdown and JSON commonly cite the marker syntax in prose / fixtures, so they're excluded — those occurrences would otherwise generate noisy "scaffold present" warnings on every project that documents how scaffolds work.

func Name

func Name() string

Name returns the command name users should type to invoke Forge. It prefers the recorded mount route (RecordCmdRoute): a standalone binary reports its own basename (users literally type that name), an embedded mount reports "<basename> forge" (e.g. "reliant forge"). Without a recording it falls back to the legacy basename heuristic. Shared so group commands can print copy-pasteable next-step hints without importing internal/cli.

func ProjectDirOverride added in v0.1.45

func ProjectDirOverride() (string, bool)

ProjectDirOverride reports the installed resolution root, if any.

func ProjectRoot

func ProjectRoot() (string, error)

ProjectRoot finds the project root by looking for forge.yaml in the resolution root — --project-dir when set, else the cwd (NOT a walk-up; see FindProjectRoot for that). Returns a user-facing error when forge.yaml is absent from that directory.

func RecordCmdRoute added in v0.1.45

func RecordCmdRoute(forgeRoot *cobra.Command)

RecordCmdRoute walks from forge's root command up to the executed tree's real root and records the subcommand tokens between them. Called by the forge root PersistentPreRun on every invocation.

func ReservedServiceNameList added in v0.1.45

func ReservedServiceNameList() []string

ReservedServiceNameList returns the reserved names in stable order, for error messages and help text. Nothing else enumerates them, and a name that is rejected without the set being visible sends people guessing — `job` in particular is the natural noun for a whole class of domains (field service, construction, scheduling, print, logistics).

func ResetCmdRoute added in v0.1.45

func ResetCmdRoute()

ResetCmdRoute clears the recorded route. Test hook only — production code records exactly once per process, at dispatch.

func ResolutionRoot added in v0.1.45

func ResolutionRoot() (string, error)

ResolutionRoot returns the directory project lookup should start from: the --project-dir override when one is installed, otherwise os.Getwd(). This is the single seam every project-locating helper goes through.

func SetProjectDir added in v0.1.45

func SetProjectDir(dir string) error

SetProjectDir installs dir as the resolution root for subsequent project lookups. A relative dir resolves against the current working directory. An empty dir clears the override, restoring os.Getwd() resolution.

It rejects a path that is not an existing directory, so a mistyped -C fails loudly here rather than degrading into a confusing "no project found" (or, worse, a silent fallback to "." at one of the call sites that ignores the lookup error).

func StrictGroup added in v0.1.45

func StrictGroup(cmd *cobra.Command) *cobra.Command

StrictGroup makes a command-GROUP (a command that exists only to host subcommands) reject an unrecognised subcommand instead of reporting success.

Cobra's default for a non-runnable parent is to print help and exit 0 for ANY leftover argument: `forge db bogus`, `forge env bogus`, a renamed verb typed with its old spelling — all printed a help page and exited 0. For a human that reads as "nothing happened"; for a scripted agent it reads as "the command succeeded", and the run continues on top of work that was never done. That is the same defect as a success message that proves nothing, just spelled with an exit code.

StrictGroup gives the group an Args validator (which makes Runnable() true, so cobra actually validates the leftover args) and a RunE that prints help for the bare form. Bare `forge db` still prints help and exits 0 — the user asked for the menu and got it. `forge db bogus` now exits non-zero naming the offending token, plus a "did you mean" line when one of the group's own subcommands is close.

Every group in the tree must go through here; TestEveryCommandGroupRejects UnknownSubcommands (internal/cli) walks the assembled tree and fails on any parent command that still carries cobra's permissive default.

func ValidateFrontendName

func ValidateFrontendName(name string) error

ValidateFrontendName checks that a frontend name is filesystem-safe.

func ValidateIdentifier

func ValidateIdentifier(name string) error

ValidateIdentifier checks that a name is valid for use as a service, worker, or operator name. Hyphens and underscores are allowed in the display name; templates use snakeCase/pascalCase helpers to convert when a Go identifier is needed (e.g. "admin-server" / "admin_server" -> package "admin_server" and field "AdminServer" — snake_case is the canonical on-disk form post-2026-06-08). The leading-character and reserved-word rules match ValidateProjectName so all top-level scaffold names share one shape.

func ValidateImportablePackageName added in v0.1.45

func ValidateImportablePackageName(name string) error

ValidateImportablePackageName rejects a component name whose Go package cannot be imported. A service, worker, operator or library becomes a package that other code imports — internal/app imports every component — and Go refuses to import package main ("is a program, not an importable package"). Without this check the name is accepted and the project fails at go build, far from the command that chose it. This is a Go language rule, not a forge reservation, so it is the only name checked here.

func ValidateProjectName

func ValidateProjectName(name string) error

ValidateProjectName checks that a project name is valid for use as a directory name and in Go module paths. Hyphens are allowed since they are valid in module paths and directory names; templates use snakeCase/pascalCase helpers to convert when a Go identifier is needed.

func ValidateServiceDirConsistency added in v0.1.45

func ValidateServiceDirConsistency(protoServiceName, dirName string) error

ValidateServiceDirConsistency checks that a proto service name and its containing proto/services/<dir>/ directory name generate the SAME Go identifiers from forge's two independent generators:

  • buf (protoc-gen-connect-go) names its Connect stubs from the PROTO service name: New<ProtoName>Handler, Unimplemented<ProtoName>Handler, <ProtoName>Name.
  • forge names its bootstrap wiring from the DIRECTORY: Mount<Pascal(dir)>, NewTest<Pascal(dir)>, <Pascal(dir)>TestOption.

These agree only when protoName == pascalCase(dir) + "Service" — exactly what `forge scaffold service <dir>` writes into a fresh proto file. Once a proto is hand-edited (e.g. "WorkOrderService" in a directory scaffolded as "workorder"), the two generators silently diverge and the mismatch surfaces three layers downstream as a Go compile error ("undefined: workorderv1connect.UnimplementedWorkOrderServiceHandler (but have UnimplementedWorkorderServiceHandler)") with no indication of the proto/directory naming as the cause. This check catches it at the source.

func ValidateServiceName

func ValidateServiceName(name string) error

ValidateServiceName checks that a name is valid for a service and not a reserved service name. For background workers use 'forge scaffold worker <name>'.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL