net10.0
Storage core for Koan: contracts, orchestrator, routing, and options.
Published
May 16, 2026
5mo ago
Total Downloads
5.1K
5,117
Install
dotnet add package Sylin.Koan.Storage --version 0.8.0
| Product | Versions |
|---|---|
| .NET |
README
Koan.Storage
Storage orchestrator for Koan apps. Simple, profile-based routing with first-class DX to create, read, probe, copy, move, and delete objects across providers.
What it does
- Routing: Resolves profile → provider+container using options or rules with safe defaults.
- Orchestration: Streams data and computes SHA-256 for seekable uploads; supports range reads.
- Capabilities: Leverages provider features like server-side copy; presign when available.
- DX: Small, async helpers without Async suffix and a model-centric API for clean calls.
Setup
- Registration: Packages auto-register via the framework pipeline. Call
AppBootstrapper.InitializeModules(services)once. Providers (e.g., Local) self-register. - Core options:
Koan:Storage:Profiles:<name>→{ Provider, Container }Koan:Storage:DefaultProfile→ string (optional)Koan:Storage:FallbackMode→Disabled | SingleProfileOnly | NamedDefault(defaultSingleProfileOnly)Koan:Storage:ValidateOnStart→bool(defaulttrue)
Notes
- Ambient DI: APIs resolve
IStorageServicefromAppHost.Current. In app host, this is set during startup (built into Koan templates).
Model‑centric API (recommended)
Bind a model type to a profile (and optionally a default container) and use concise statics/instance ops.
// Bind to profile "hot" (container optional; provider+container resolve via options)
[Koan.Storage.Infrastructure.StorageBinding("hot")]
public sealed class FileA : Koan.Storage.Model.StorageEntity<FileA> { }
[Koan.Storage.Infrastructure.StorageBinding("cold")]
public sealed class FileB : Koan.Storage.Model.StorageEntity<FileB> { }
// Create → Read → Copy/Move
var rec = await FileA.CreateTextFile("name.txt", "hello");
var text = await FileA.Get(rec.Key).ReadAllText();
await FileA.Get(rec.Key).CopyTo<FileB>();
await FileA.Get(rec.Key).MoveTo<FileB>();
// Other instance ops
var bytes = await FileA.Get(rec.Key).ReadAllBytes();
var head = await FileA.Get(rec.Key).Head(); // ObjectStat
Contract
- Inputs:
key, optionalname, content (string/byte[]/Stream/ object for JSON), optionalcontentType. - Outputs:
IStorageObjectwith metadata (Id,Key,Name,ContentType,Size,ContentHash,CreatedAt,UpdatedAt,Provider,Container,Tags). - Errors: Unknown profile/container → throws; missing key →
nullforHead,falseforDelete; invalid range → throws. Hash computed only on seekable streams.
Service helpers (alternative)
The same primitives are available directly on IStorageService.
await storage.CreateTextFile("doc.txt", "hello", profile: "main");
var text = await storage.ReadAllText("main", "", "doc.txt");
var stat = await storage.HeadAsync("main", "", "doc.txt");
await storage.CopyTo("hot", "", "doc.txt", "cold");
Behavioral notes and edge cases
- Defaults and fallbacks: If profile is omitted,
DefaultProfileis used when set; with exactly one profile,SingleProfileOnlyfallback applies. - Validation: With
ValidateOnStart=true, misconfigurations fail fast during app start. - Large payloads: Use
ReadRangeAsString/ReadRangeAsyncto avoid loading entire content. - Capabilities: Local provider supports lightweight stat and server-side copy; presign is unsupported.
References
- Reference:
docs/reference/storage.md - Decisions:
STOR-0001,STOR-0006,STOR-0007,DATA-0061,ARCH-0040
Adoption Assessment
Assess this package against its supported frameworks, license, maintenance signals and dependency graph before making it a project standard.
Compatibility metadata lists 1 target framework; confirm the exact target used by your application.
Related Guides & Workflows
Learn how to evaluate, integrate, or audit this package in your .NET project.