Documentation
¶
Overview ¶
Package inspector reads the structure of an ESB-generated project without writing anything. It walks the file tree produced by `esb init` and surfaces an in-memory ProjectModel that the printer turns into a single-screen summary.
Declaration-based facts (aggregates, events, handlers, queries, projection aggregate lists) are recovered with go/ast, so the scanner is indifferent to gofmt spacing and comment wording and never treats an unrelated struct as an event. The few marker-anchored blocks the generator injects into hand-shaped slices (wire App fields/init, AutoMigrate models, main.go workers) are still read by locating their `// esb:inject:*` markers, because there the contract is precisely "what was injected after this marker", not a declaration.
Index ¶
Constants ¶
const ( StorageModeEmbedded = "embedded" StorageModeESBServer = "esb-server" // StorageModeUnknown marks an unrecognised EVENT_STORE_MODE value. // The UI displays it as a warning so a typo (e.g. "esb-sever") // is not silently treated as embedded. StorageModeUnknown = "unknown" )
StorageMode values the inspector recognizes in EVENT_STORE_MODE.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Aggregate ¶
type Aggregate struct {
Name string // aggregate-store name from the generated constant (for example "bank-account")
FileName string // snake_case file name (without .go), used to identify the root struct
Events []string
EventDetails []EventDetail
}
Aggregate is one file in domain/ (excluding event.go / errors.go).
type EventDetail ¶
type EventDetail struct {
Name string
Fields []EventField
}
EventDetail describes one event's fields, extracted from its generated struct declaration in domain/<aggregate>.go. Fields is empty when the event name was found only via an Apply() case branch with no matching generated struct (e.g. a hand-written event that skipped `esb add event`).
type EventField ¶
type EventField struct {
Name string // Go field name, PascalCase
Type string // Go type as written (string, int64, ...)
JSONTag string
}
EventField is one field of a generated event struct.
type Handler ¶
type Handler struct {
Name string // snake_case file name (without .go)
Aggregate string // resolved via the service field ("" if not detected)
}
Handler is one file in server/handler/.
type LockInfo ¶
type LockInfo struct {
Key string
OwnerToken string
ExpiresAt time.Time
Held bool // false when ExpiresAt is in the past
}
LockInfo describes one row from the embedded "locks" table.
type NotFound ¶
type NotFound struct {
Dir string
}
NotFound is returned when Scan is run outside an ESB project (no go.mod).
type ProjectModel ¶
type ProjectModel struct {
ModuleName string
PackageName string
Aggregate []Aggregate // every aggregate discovered in domain/, sorted by aggregate-store name
Projection []Projection
Handler []Handler
Query []Query
Wire WireGraph
Migrate []string // GORM models in projection/db.go AutoMigrate
RunWorker []string // workers in main.go
Storage StorageInfo // event store mode + per-aggregate event counts
}
ProjectModel is the in-memory picture of one ESB project.
func Scan ¶
func Scan(rootDir string) (ProjectModel, error)
Scan walks rootDir and returns a populated ProjectModel. A missing go.mod is reported as *NotFound so the CLI can print a friendly message.
type Projection ¶
type Projection struct {
Name string // worker file name without _worker.go suffix
Multi bool
Aggregates []string // aggregate names listened to
}
Projection is one projection worker. Multi is true when the worker applies events from several aggregates (the worker file contains a `switch e.AggregateName` branch, or declares a "<name>AggregateNames" slice).
type Query ¶
type Query struct {
Name string
Aggregate string // best-effort: derived from the row type the function returns
}
Query is one query function in projection/query.go.
type Storage ¶
type Storage struct {
Info StorageInfo
}
Storage exposes the storage mode + per-aggregate event counts for the UI. It is populated by ScanStorage and attached to the ProjectModel by Scan.
type StorageInfo ¶
type StorageInfo struct {
// Mode is "embedded" or "esb-server". When the .env has no
// EVENT_STORE_MODE entry the inspector defaults to "embedded"
// because that is what `esb init` generates today.
Mode string
// DSN is the SQLite path used by the embedded event store, or
// empty when mode == esb-server. The path is resolved against
// the project root so relative DSNs ("app.db") display as
// "<root>/app.db" in the UI.
DSN string
// ESBURL is the remote endpoint when mode == esb-server, or
// empty otherwise.
ESBURL string
// Counts maps aggregate_name -> event row count, populated from
// the embedded SQLite file when mode == embedded and the file
// exists. Counts is nil otherwise.
Counts map[string]int
// SnapshotCounts maps aggregate_name -> snapshot row count, same
// scope/lifetime rules as Counts. A project generated before
// snapshot support existed simply has no "snapshots" table yet —
// that surfaces as an empty map, not an error.
SnapshotCounts map[string]int
// EventCounts maps aggregate_name -> event_name -> stored row count,
// populated from the embedded SQLite file (embedded mode only). Used
// to warn before deleting an event definition whose events already
// exist in history. Nil in esb-server mode or when the file is absent.
EventCounts map[string]map[string]int
// Locks lists the rows currently in the embedded "locks" table
// (both held and expired-but-not-yet-cleaned-up), sorted by key.
// Only populated in embedded mode — esb-server mode exposes no
// "list all locks" endpoint, only per-key lookups.
Locks []LockInfo
// HasSQLite reports whether the embedded SQLite file was
// opened successfully. When false, Counts is nil even if the
// DSN points somewhere — a useful signal for the UI so the
// page can render "no events yet" instead of pretending the
// table exists.
HasSQLite bool
}
StorageInfo describes how the project's event store is currently configured. It is read-only — the inspector never mutates the project. Embedded mode points at a local SQLite file; esb-server mode points at a remote HTTP endpoint.
func ScanStorage ¶
func ScanStorage(rootDir string) StorageInfo
ScanStorage inspects rootDir for the project's event store configuration. It is tolerant: a missing .env, an unparseable EVENT_STORE_MODE, or a missing SQLite file all surface as a zero-value StorageInfo with sensible defaults rather than errors.
The function is intentionally cheap — it runs on every UI page load. SQLite is opened read-only with no busy timeout; a corrupt file surfaces as HasSQLite=false without failing the rest of the scan.
func (StorageInfo) EventCount ¶
func (s StorageInfo) EventCount(aggregateName, eventName string) int
EventCount returns how many rows are stored for (aggregateName, eventName) in embedded mode, or 0 when unknown (esb-server mode, no SQLite, or none).
func (StorageInfo) HeldLockCount ¶
func (s StorageInfo) HeldLockCount() int
HeldLockCount returns how many rows in Locks are currently held (not expired). Expired-but-not-yet-cleaned-up rows are excluded.
func (StorageInfo) SortedAggregateNames ¶
func (s StorageInfo) SortedAggregateNames() []string
SortedAggregateNames returns the aggregate names from the count map in lexical order. The UI uses it to render a stable table without depending on Go's randomized map iteration.
func (StorageInfo) String ¶
func (s StorageInfo) String() string
String renders a one-line summary suitable for the inspector's CLI output. Keep it stable — the snapshot golden file pins the exact wording.
func (StorageInfo) TotalEvents ¶
func (s StorageInfo) TotalEvents() int
TotalEvents sums Counts into a single number for the dashboard card. Returns 0 when Counts is empty.
func (StorageInfo) TotalSnapshots ¶
func (s StorageInfo) TotalSnapshots() int
TotalSnapshots sums SnapshotCounts into a single number for the dashboard card. Returns 0 when no snapshots have been taken yet.
type WireGraph ¶
type WireGraph struct {
Fields []WireNode // declared fields on App (besides Env/Handler)
Nodes []WireNode // constructor expressions inside NewApp
}
WireGraph is the deconstructed wire/wire.go App.
type WireNode ¶
type WireNode struct {
VarName string // local var in NewApp, e.g. "orderWorker"
Field string // matching App field, e.g. "OrderProjectionWorker"
Type string // concrete type, e.g. "*projection.OrderProjectionWorker"
Provider string // constructor call, e.g. "projection.NewOrderProjectionWorker(...)"
}
WireNode is one provider edge in the wire graph.