Lyo.Config
1.0.6
dotnet add package Lyo.Config --version 1.0.6
NuGet\Install-Package Lyo.Config -Version 1.0.6
<PackageReference Include="Lyo.Config" Version="1.0.6" />
<PackageVersion Include="Lyo.Config" Version="1.0.6" />
<PackageReference Include="Lyo.Config" />
paket add Lyo.Config --version 1.0.6
#r "nuget: Lyo.Config, 1.0.6"
#:package Lyo.Config@1.0.6
#addin nuget:?package=Lyo.Config&version=1.0.6
#tool nuget:?package=Lyo.Config&version=1.0.6
Lyo.Config
Typed, definition-driven configuration for per-entity values (a Discord guild, a tenant). The abstract API lives here. PostgreSQL persistence is in Lyo.Config.Postgres.
Concepts
| Piece | Role |
|---|---|
ConfigDefinitionRecord |
Declares an allowed key for an ForEntityType (CLR type name string), the CLR value type, optional default, IsRequired, and metadata. |
ConfigBindingRecord |
Stores the actual value for one entity instance (EntityRef: type + id) under a definition. |
ConfigValue |
Wrapper: CLR type name + JSON payload. Serialize/deserialize with ConfigJsonSerializerOptions.Default when you do not pass custom JsonSerializerOptions. |
ResolvedConfigRecord |
Produced by LoadConfigAsync: every definition for that entity type, each with optional binding; Value is binding ?? default. |
Definitions are unique per (ForEntityType, Key). Bindings are unique per (DefinitionId, ForEntityType, ForEntityId). In PostgreSQL, config_binding has a value_type column (
same CLR type name as config_definition.for_value_type, denormalized for querying and exports).
JSON
ConfigJsonSerializerOptions.Default is used whenever ConfigValue callers pass null for options: camelCase property names, case-insensitive deserialization, omit nulls when writing. Keeps API JSON and stored value_json aligned.
IsRequired
If IsRequired is true and the definition has no default (DefaultValue null), each entity must have a binding for that key. - LoadConfigAsync calls ResolvedConfigRecord.ValidateRequired() and throws if any required key has no resolved value. - DeleteBindingAsync / DeleteBindingsAsync refuse to remove a binding that would violate that rule. If IsRequired is true and a default exists, the default supplies the resolved value when no binding exists (deleting the binding is allowed).
Deleting definitions
DeleteDefinitionAsync removes the definition row. In PostgreSQL, config_binding rows referencing that definition are removed by foreign-key ON DELETE CASCADE.
Versioning
Two version stories:
Versioning. 1. CLR / definition type changes
Each definition's ForValueType is the CLR type name for the stored JSON, same convention as ForEntityType: Type.FullName (same form as ConfigValue.TypeName; use ConfigValue.GetTypeName(typeof(T)) when seeding). If you rename types, split types, or change the JSON shape incompatibly: - Update the definition (and seeders) so ForValueType matches the new type. - Migrate existing value_json (or delete bindings and recreate), or introduce a new key and deprecate the old one. The Lyo.Config layer does not auto-migrate arbitrary payloads.
Versioning. 2. Document schema version inside the JSON (optional pattern)
For a single JSON document stored as one binding (e.g. DiscordGuildSettings), use an integer Version field and a CurrentSchemaVersion constant on the model:
NormalizeForRead()AfterGetValue<T>(), fix legacy documents (e.g.Version <= 0or older version numbers): set defaults for new properties, rewrite fields, then setVersionto the version you've upgraded to.NormalizeForPersistence()BeforeConfigValue.From, call this so every save writesVersion == CurrentSchemaVersion.
When you add a breaking or additive shape change: bump CurrentSchemaVersion, extend NormalizeForRead() with if (Version == n) { …; Version = n + 1; } (or jump
straight to current), and deploy readers before or with writers.
This is application-level migration inside one binding value; it does not replace backups or one-off SQL migrations when you need them.
Versioning. 3. Binding value history (revert)
PostgreSQL stores append-only revisions in config.config_binding_revision: primary key is (binding_id, revision) (no separate row id). Each successful SaveBindingAsync writes a new row with a monotonic revision number (1-based per binding). The current value still lives on config_binding for fast reads.
GetBindingRevisionsAsync/GetBindingRevisionAsync. Inspect history (newest first in the list overload).RevertBindingToRevisionAsync. Copies the snapshot atrevisiononto the binding and appends a new revision (so the timeline stays linear and "revert" is auditable).
Deleting a binding (or its definition) cascades and removes revision rows. The initial migration seeds revision 1 from each existing binding's current value so history starts at deploy time.
IConfigStore at a glance
SaveDefinitionAsync(ConfigDefinitionRecord)upserts.GetDefinitionByIdAsync(Guid)/GetDefinitionAsync(string forEntityType, string key)look up one definition.GetDefinitionsAsync(string forEntityType)enumerates definitions for a type.DeleteDefinitionAsync(Guid)deletes. Postgres cascades toconfig_bindingrows.
AppConfigEntity
AppEntityType = "App"(the storedEntityRef.EntityTypefor app-scoped definitions and bindings).ToEntityRef(string appKind, string appId)/TryCreate(...)URI-decode each segment, lowercase, validate the slug character set (a-z,0-9,-,_,., length ≤ 128), and producenew EntityRef("App", $"{kindNorm}:{idNorm}"). This is the compound-id shape thatConfigBindingRecord.ForEntityIdis sized for (string, notGuid).
See also
Lyo.Config.Postgres. EF Core schema (configschema),PostgresConfigStore, migrations.Lyo.EntityReference.Models.EntityRefused throughout the binding APIs.
Dependencies
Generated from ProjectReference / PackageReference (same model as docs/Lyo.ProjectGraph.html).
Lyo.Common(direct, lyo)Lyo.EntityReference.Models(direct, lyo)System.Text.Json10.0.5(direct, microsoft, netstandard2.0)Lyo.Exceptions(transitive, lyo)Microsoft.Extensions.Logging.Abstractions10.0.5(transitive, microsoft)System.Memory4.6.3(transitive, microsoft, netstandard2.0)
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- Lyo.Common (>= 1.0.6)
- Lyo.EntityReference.Models (>= 1.0.6)
- System.Text.Json (>= 10.0.5)
-
net10.0
- Lyo.Common (>= 1.0.6)
- Lyo.EntityReference.Models (>= 1.0.6)
NuGet packages (4)
Showing the top 4 NuGet packages that depend on Lyo.Config:
| Package | Downloads |
|---|---|
|
Lyo.Config.Api.Models
Shared contracts for the Lyo central Config API (resolve outcomes). |
|
|
Lyo.Config.Api
Central HTTP API exposing Lyo.Config PostgreSQL-backed IConfigStore for microservices (polling-friendly ETags). Embed via AddConfigApi / MapConfigApiEndpoints. |
|
|
Lyo.Discord.Postgres
PostgreSQL persistence for Discord entities (EF Core, schema discord). |
|
|
Lyo.Config.Postgres
PostgreSQL implementation of Lyo.Config using Entity Framework Core and jsonb-backed typed values. |
GitHub repositories
This package is not used by any popular GitHub repositories.