https://github.com/origadmin/kore
https://github.com/origadmin/kore
Last synced: 2 months ago
JSON representation
- Host: GitHub
- URL: https://github.com/origadmin/kore
- Owner: origadmin
- License: mit
- Created: 2026-03-09T08:08:37.000Z (3 months ago)
- Default Branch: main
- Last Pushed: 2026-03-09T08:44:33.000Z (3 months ago)
- Last Synced: 2026-03-09T12:47:20.107Z (3 months ago)
- Language: Go
- Size: 41 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 5
-
Metadata Files:
- Readme: README.md
- Contributing: .github/CONTRIBUTING.md
- Funding: .github/FUNDING.yml
- License: LICENSE
- Code of conduct: .github/CODE_OF_CONDUCT.md
- Codeowners: .github/CODEOWNERS
- Security: .github/SECURITY.md
Awesome Lists containing this project
README
# Kore
Kore is a lightweight, clean, and highly extensible Dependency Injection (DI) framework for Go. It focuses on the clean separation of **Discovery** (locating dependencies) and **Identity** (component metadata), providing a predictable and type-safe way to manage complex component graphs.
## Key Features
- **Clean Architecture**: Separates navigation (`Locator`) from instantiation context (`Handle`).
- **Discovery vs Identity**: Components can find others via locators without leaking their own internal state.
- **Multidimensional Isolation**: Support for Categories, Scopes, and Capability Tags.
- **Lazy Initialization**: Components are instantiated only when first requested.
- **Circular Dependency Detection**: Built-in safety against recursive dependency chains.
- **Zero External Dependencies**: Pure Go implementation.
## Installation
```bash
go get github.com/origadmin/kore
```
## Quick Start
### 1. Define Your Components
```go
type Database struct {
DSN string
}
type Logger struct {
Prefix string
}
type Service struct {
db *Database
logger *Logger
}
```
### 2. Register Providers
```go
import "github.com/origadmin/kore"
reg := kore.New()
// Register a Logger
reg.Register("logger", func(ctx context.Context, h kore.Handle) (any, error) {
return &Logger{Prefix: "[APP]"}, nil
})
// Register a Database with dependency on Logger
reg.Register("database", func(ctx context.Context, h kore.Handle) (any, error) {
// Find Logger using Locator
logger, _ := kore.GetDefault[*Logger](ctx, h.Locator().In("logger"))
return &Database{DSN: "localhost:5432"}, nil
})
```
### 3. Load and Use
```go
ctx := context.Background()
reg.Load(ctx, nil) // Load configurations
// Retrieve the database
db, err := kore.GetDefault[*Database](ctx, reg.In("database"))
```
## Core Concepts: The Multi-dimensional DI
Kore organizes components into a three-dimensional coordinate system, allowing for precise control over component visibility and lifecycle.
### 1. Horizontal Dimension: Categories
Categories define **what** a component is (e.g., `database`, `cache`, `logger`).
- **Purpose**: Grouping identical types of infrastructure.
- **Usage**: You can iterate over all components within a category or retrieve a specific one by name.
### 2. Vertical Dimension: Scopes
Scopes define **where** a component exists (e.g., `_global`, `server`, `client`).
- **Hierarchy**: Components in a specific scope are isolated from others.
- **Fallback**: Kore supports intelligent fallback mechanisms, allowing local scopes to inherit or override global defaults.
### 3. Specialization: Capability Tags
Tags define **which variant** or **what capability** a provider offers (e.g., `gateway`, `mock`, `production`).
- **Isolation**: A `Locator` created with the `gateway` tag can only "see" providers registered with that same tag (or common providers).
- **Perspective**: This allows you to create different "perspectives" of the same dependency graph for different parts of your application.
## Dual-Axis Isolation Model
Kore provides a robust isolation model that separates components along two orthogonal axes: **Vertical (Contextual)** and **Horizontal (Functional)**.
### Vertical Isolation: S-Single (Scope-based)
Vertical isolation is achieved through **Scopes**, partitioning components based on their **Runtime Environment**.
- **Mechanism**: Each Scope (e.g., `_global`, `server`, `client`) is a physically distinct instance container.
- **S-Single**: For a given `(Category, Scope, Name)`, there is exactly one instance. This ensures that a component in the `server` scope cannot accidentally reference or interfere with a component in the `client` scope, even if they share the same name.
- **Use Case**: Environment-specific overrides and lifecycle management.
### Horizontal Isolation: T-Multi (Tag-based)
Horizontal isolation is achieved through **Tags**, partitioning components based on their **Responsibility and Capability**.
- **Mechanism**: Providers register themselves with specific Capability Tags. When you enter a category via `reg.In(cat, WithInTags("gateway"))`, you create a **Perspective**.
- **T-Multi**: A single Category can house multiple providers for the same name, but only those matching the requested "Perspective Tags" (the Capability Set) are visible.
- **Responsibility Filtering**: This allows you to hide internal-only components from public-facing locators or switch between different implementation variants (e.g., `production` vs `mock`) without changing the component's name or code.
- **Inheritance**: "Common" providers (those with no tags) are visible across all horizontal perspectives, acting as a shared foundation.
## Native Configuration Binding
Unlike other DI frameworks that treat configuration as an afterthought, Kore is a **Config-First** engine.
- **The Resolver**: Every category can have a `Resolver` that maps raw input (YAML, JSON, or Map) to structured `ModuleConfig`.
- **Automatic Instantiation**: Once a config entry is mapped (e.g., a database config named `mysql`), Kore automatically knows how to use the registered `Provider` to turn that config into a live object.
- **Active Instance**: Supports an `Active` flag in configuration to designate which named instance should be the `_default` for that category.
## Comparison with Mainstream Frameworks
| Feature | Kore | Google Wire | Uber Fx / Dig |
| :--- | :--- | :--- | :--- |
| **Mechanism** | Run-time (Provider-based) | Compile-time (Code Gen) | Run-time (Reflection) |
| **Dependency Resolution** | Explicit via `Locator` | Implicit via Type Matching | Implicit via Type Matching |
| **Identity vs Search** | **Absolute Separation** | None (Single Graph) | None (Single Graph) |
| **Multi-instance Support** | Native (Category/Name/Tag) | Complex (using tags/alias) | Complex (using groups/names) |
| **Configuration Binding** | Built-in `Resolver` | Manual | Manual / External |
| **Error Detection** | First-use / Initialization | Compile-time | App Start-up |
## Why Kore? The Competitive Edge
Kore is not just another object wirer; it is a **Structured Discovery Engine**. Compared to mainstream frameworks like Google Wire or Uber Fx, Kore provides a multi-dimensional approach to dependency management.
### Feature Comparison
| Feature | Kore | Google Wire | Uber Fx / Dig |
| :--- | :--- | :--- | :--- |
| **Vertical Isolation (S-Single)** | **Native (Scopes)**: Physical isolation of instances by environment. | **None**: Single global graph; naming conflicts are manual. | **Weak**: Limited lifecycle scoping; lacks multi-layer isolation. |
| **Horizontal Filtering (T-Multi)** | **Native (Tags)**: Logical filtering of responsibilities via Perspectives. | **None**: Relies on static types or manual struct naming. | **Complex**: Requires annotations or groups; hard to maintain. |
| **Config Binding (Config-First)** | **Deeply Integrated**: Automatic mapping from raw config to instances. | **None**: Pure wiring; config handling is entirely external. | **None**: Requires external libraries; mapping is scattered. |
| **Separation (Identity/Locator)** | **Absolute (Plan A)**: Identity (Handle) is isolated from Discovery. | **Mixed**: Components have excessive visibility into the graph. | **Obscure**: Reflection leads to implicit container coupling. |
| **Multi-instance Management** | **Seamless**: Native support for N-instances via Category/Name/Tag. | **Verbose**: Requires unique types/providers for each instance. | **Heavy**: Complexity grows exponentially with instance counts. |
### The Kore Advantage
#### 1. Precision via S-Single & T-Multi
- **Vertical (S-Single)**: Ensures that your `server` database and `monitoring` database never touch, even if they share the same provider.
- **Horizontal (T-Multi)**: Allows you to define implementation variants (e.g., `public-api` vs `internal-tool`) in the same category and switch between them simply by changing the locator's perspective.
#### 2. Native Configuration-to-Instance Pipeline
Kore bridges the gap between static code and dynamic configuration. By defining a `Resolver`, you transform your DI from a static object graph into a dynamic engine that responds to your environment settings.
#### 3. Predictability over Magic
By enforcing an explicit `h.Locator().Get()` pattern, Kore removes the "magic" of reflection and the "clutter" of code generation. You gain absolute traceability of every dependency in your system.
## Architecture: Plan A (Composition)
Kore implements the **Plan A** composition pattern, where the `Handle` (Identity) provided during instantiation does not inherit from the `Locator` (Navigation). Instead, it provides a `Locator()` method. This ensures that:
1. **Identity is Local**: A component's name and config are only accessible via its own `Handle`.
2. **Navigation is Explicit**: To find another component, you must explicitly use a `Locator`.
3. **Automatic State Stripping**: Calling `In()` on a locator returns a fresh locator without any residual identity from the caller, preventing accidental state leakage.
## License
Kore is released under the MIT License.