How to Explore the jframe Repository Structure: A Developer's Guide
You explore the jframe repository structure by examining the kernel lifecycle in core/kernel/, the bootstrap logic in cmd/server/, and the module implementations in mod/ to understand how the dependency-injection container orchestrates application modules.
The jframe repository is a Go-based application framework built around modular architecture and dependency injection. To effectively explore the jframe repository structure, you must understand how the kernel engine manages module lifecycles and how the CLI bootstraps the application. This guide walks through the key directories and source files that define the framework's architecture.
Architecture Overview
The repository organizes code around three core concepts: the kernel engine, the CLI bootstrapper, and pluggable modules.
The Kernel and Engine
The heart of the framework lives in core/kernel/kernel.go and core/kernel/module.go. The Engine struct holds the dependency-injection container, configuration management, and lifecycle control. It maintains a registry of Module implementations that follow a strict interface contract.
The Module interface defines lifecycle hooks including PreInit, Init, PostInit, Load, Start, and Stop. A default UnimplementedModule provides empty implementations for convenience when creating new modules.
Server Bootstrap Entry Point
The cmd/server/server.go file serves as the primary entry point for the jframe server command. This file orchestrates the initialization sequence: it loads configuration via conf.LoadConfig, initializes optional services like Sentry, creates the kernel using kernel.New, registers modules from modList.ModList, and starts the kernel.
Module System
Concrete implementations of the kernel.Module interface reside under mod/. The mod/example/mod.go file demonstrates how to register dependencies using h.Map, retrieve them via h.Value, h.Invoke, or h.Load, and expose HTTP routes through the embedded jin engine. Real applications extend this pattern by adding custom modules to the modList.ModList registry.
Bootstrap Flow and Lifecycle
Understanding the execution flow helps you navigate the codebase effectively:
-
Command execution –
main.gocallscmd.Execute(), which routes to theserversub-command incmd/server/server.go. -
Configuration loading –
conf.LoadConfigreads YAML files or environment variables via Viper and populates the global configuration accessible throughconf.Get(). -
Kernel creation –
kernel.Newinstantiates anEnginecontaining the DI container. The kernel receives shared resources includingconnandtcpMux. -
Module registration –
k.RegMod(modList.ModList...)stores each module by name in theEngine.modulesmap. -
Lifecycle execution –
k.StartModule()iterates through registered modules, performing config unmarshalling and executing hooks in sequence:PreInit→Init→PostInit→Load→Start. Each phase runs in its own goroutine where appropriate. -
Graceful shutdown – On SIGINT or SIGTERM signals,
k.Stop()invokes each module'sStopmethod and waits for all goroutines to finish.
Navigating the Source Code
When you explore the jframe repository structure, use these targeted approaches to locate specific functionality:
-
Locate modules – All modules live under
mod/. Each subdirectory contains amod.gofile implementingkernel.Module. Use grep to find module definitions:grep -R "type .* struct" mod/*/mod.go -
Trace dependency injection – The framework uses juanjiTech/inject/v2. The kernel's
Hubembeds aninject.Injector. Query the container withh.Value,h.Invoke, orh.Loadto understand how components receive their dependencies. -
Examine HTTP routing – The default router is jin (
github.com/juanjiTech/jin). Modules retrieve a*jin.Enginefrom the injector and register routes, as demonstrated in the example module.
Practical Code Examples
Listing Registered Modules at Runtime
Inspect the engine's module registry after initialization to verify active components:
func ListModules(e *kernel.Engine) {
for name := range e.modules {
fmt.Println("registered module:", name)
}
}
Call this after k.RegMod(...) to confirm which modules are loaded.
Registering Dependencies in a Module
Provide shared resources to the DI container during the Init phase:
func (m *MyMod) Init(h *kernel.Hub) error {
db, err := sql.Open("postgres", conf.Get().PostgresDSN)
if err != nil {
return err
}
h.Map(db)
return nil
}
Retrieving Dependencies in Another Module
Consume shared resources during the Load phase:
func (m *AnotherMod) Load(h *kernel.Hub) error {
var db *sql.DB
if err := h.Load(&db); err != nil {
return err
}
return nil
}
Adding HTTP Routes from a Module
Expose endpoints by interacting with the jin router:
func (m *MyMod) Load(h *kernel.Hub) error {
var router *jin.Engine
if err := h.Load(&router); err != nil {
return err
}
router.GET("/hello", func(c *jin.Context) {
_, _ = c.Writer.WriteString("Hello from MyMod")
})
return nil
}
Key Files Reference
These files provide the definitive map for exploring the codebase:
core/kernel/kernel.go– Engine implementation and lifecycle orchestrationcore/kernel/module.go–Moduleinterface andUnimplementedModulebasecmd/server/server.go– Server command, configuration loading, and kernel bootconf/config.go– Global configuration struct and defaultsmod/example/mod.go– Sample module demonstrating DI patterns and routingmod/example/modList/list.go– Central registry where modules are listed for bootstrappingpkg/sentry/sentry.go– Optional Sentry integration used by the serverpkg/ip/ip.go– Network interface utilities for UI output
Summary
- Start with
core/kernel/to understand theEnginestruct andModuleinterface that govern the framework lifecycle - Study
cmd/server/server.goto see how the application bootstraps configuration, creates the kernel, and registers modules - Explore
mod/directories to find concrete module implementations showing dependency injection and HTTP routing patterns - Use the
Hubmethods (Map,Load,Invoke) to trace how components interact through the juanjiTech/inject/v2 container - Reference
conf/config.goto understand the configuration structure populated by Viper
Frequently Asked Questions
Where should I start when exploring the jframe repository structure?
Begin with core/kernel/kernel.go and core/kernel/module.go to understand the foundational interfaces. Then examine cmd/server/server.go to see how the kernel initializes during application startup. This sequence provides the architectural context needed to understand specific modules in mod/.
How does jframe handle dependency injection between modules?
The framework uses juanjiTech/inject/v2 through the kernel.Hub type. Modules register dependencies using h.Map() during Init, and retrieve them using h.Load() or h.Invoke() during Load or Start phases. The Engine maintains a single injector instance shared across all modules.
What is the purpose of the modList in jframe?
The modList (typically found in mod/example/modList/list.go or similar) serves as the central registry where developers list active modules. The server bootstrap code iterates over this list when calling k.RegMod(), determining which modules participate in the application lifecycle.
How do I add a new module to the jframe repository?
Create a new subdirectory under mod/ containing a mod.go file that implements the kernel.Module interface. Embed kernel.UnimplementedModule to satisfy the interface with minimal boilerplate, then override the lifecycle hooks you need (typically Init for dependency registration and Load for route setup). Finally, add your module to the modList.ModList in the list file to ensure the kernel loads it during startup.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →