0.5.1-pre.002
This commit is contained in:
68
ks-config/CHANGELOG.md
Normal file
68
ks-config/CHANGELOG.md
Normal file
@@ -0,0 +1,68 @@
|
||||
<!-- file: ks-config/CHANGELOG.md -->
|
||||
<!-- version: 12 -->
|
||||
|
||||
# CHANGELOG — ks-config
|
||||
|
||||
## `0.5.1-pre.002`
|
||||
|
||||
- renomme `kb-config` en `ks-config` et l'identifiant Rust `kb_config` en `ks_config` ;
|
||||
- met à jour les chemins TS-RS source vers `frontend/ts/bindings/ks_config` sans livrer les bindings générés ;
|
||||
- conserve le format de configuration et les variables d'environnement historiques jusqu'aux prereleases dédiées.
|
||||
|
||||
## `0.5.0-pre.002`
|
||||
|
||||
- confirme pour `0.5.1` le split de la configuration générale et du logging en documents et schémas distincts ;
|
||||
- fixe la convention cible `KS_SECRET_*` / `KS_PUBLIC_*` / `KS_*` pour les variables d’environnement propres au projet ;
|
||||
- documente la séparation future source/runtime/public et interdit l’usage diagnostic du JSON résolu complet ;
|
||||
- précise les tâches de migration, tests externes et non-divulgation sans modifier encore le contrat runtime `0.4.8`.
|
||||
|
||||
## 0.4.6
|
||||
|
||||
- alignement de la crate sur la version fonctionnelle bot3 `0.4.6` ;
|
||||
- clôture des tâches de migration applicables et report explicite des évolutions ultérieures dans le TODO.
|
||||
|
||||
## 0.1.0-pre.075
|
||||
|
||||
- validation statique que `ks-config` reste l’unique propriétaire direct de `dotenvy` ;
|
||||
|
||||
## 0.1.0-pre.073
|
||||
|
||||
- ajout du guide transversal [`docs/guides/CONFIGURATION.md`](../docs/guides/CONFIGURATION.md) ;
|
||||
|
||||
## 0.1.0-pre.072
|
||||
|
||||
- reclassement du TODO selon les blocants avant `0.4.6`, les travaux `0.4.7`, les versions ultérieures et les dépendances conditionnelles.
|
||||
|
||||
## 0.1.0-pre.070
|
||||
|
||||
- enrichissement de `USAGE.md` avec plusieurs exemples couvrant les familles d’API publiques significatives.
|
||||
|
||||
## 0.1.0-pre.069
|
||||
|
||||
### Documentation
|
||||
|
||||
- création de `TODO.md`, `USAGE.md` et du changelog détaillé ;
|
||||
- réécriture du README selon l’architecture bot3 ;
|
||||
- suppression de la section `Non publié`, incompatible avec le rôle chronologique du changelog ;
|
||||
- retrait des limitations et travaux futurs, désormais maintenus dans `TODO.md` ou `USAGE.md` selon leur nature ;
|
||||
- clarification de la séparation entre historique de prerelease et objectifs futurs ;
|
||||
- réécriture de `TODO.md` sous forme de tâches uniquement ;
|
||||
- correction des exemples de `USAGE.md` afin de ne pas utiliser l’opérateur `?`.
|
||||
|
||||
## 0.1.0
|
||||
|
||||
### Migré
|
||||
|
||||
- migration et consolidation de la configuration typée bot2 dans `ks-config` ;
|
||||
- conservation du schéma JSON, des profils, endpoints, listeners, paramètres de stockage, logging, wallet et exécution.
|
||||
|
||||
### Modifié
|
||||
|
||||
- adoption des règles Rust 2024 et Khadhroony ;
|
||||
- export TypeScript contrôlé des types destinés au frontend ;
|
||||
- validation structurée par `ks_core::Error`.
|
||||
|
||||
### Validation
|
||||
|
||||
- validation de l’exemple contre le schéma ;
|
||||
- tests de round-trip, profils actifs, placeholders, URLs, rôles et invariants opérationnels.
|
||||
20
ks-config/Cargo.toml
Normal file
20
ks-config/Cargo.toml
Normal file
@@ -0,0 +1,20 @@
|
||||
# file: ks-config/Cargo.toml
|
||||
# version: 4
|
||||
|
||||
[package]
|
||||
name = "ks-config"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
publish.workspace = true
|
||||
|
||||
[dependencies]
|
||||
dotenvy.workspace = true
|
||||
ks-core = { path = "../ks-core" }
|
||||
jsonschema.workspace = true
|
||||
serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
ts-rs.workspace = true
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
41
ks-config/README.md
Normal file
41
ks-config/README.md
Normal file
@@ -0,0 +1,41 @@
|
||||
<!-- file: ks-config/README.md -->
|
||||
<!-- version: 6 -->
|
||||
|
||||
# ks-config
|
||||
|
||||
`ks-config` définit le contrat de configuration typé du workspace, son schéma JSON embarqué et les fonctions de chargement, résolution d’environnement, validation et sérialisation.
|
||||
|
||||
## Responsabilités
|
||||
|
||||
- exposer `AppConfig` et les sections de configuration publiques ;
|
||||
- valider le JSON contre le schéma embarqué ;
|
||||
- appliquer les invariants métier après désérialisation ;
|
||||
- charger `.env` et `.env.local` depuis la racine du workspace ;
|
||||
- résoudre les placeholders `${NAME}` et `${NAME:-fallback}` ;
|
||||
- sélectionner le profil actif ;
|
||||
- exporter les types nécessaires au frontend avec `ts-rs`.
|
||||
|
||||
## Hors périmètre
|
||||
|
||||
La crate n’initialise ni le logging, ni PostgreSQL, ni les transports et ne manipule aucun secret de wallet. Elle fournit uniquement la configuration validée à ces consommateurs.
|
||||
|
||||
## Surface publique
|
||||
|
||||
Les principales fonctions sont `read_config_json_file_with_environment`, `parse_config_json`, `validate_config`, `validate_config_json_schema`, `active_profile` et les sérialiseurs JSON. Les types publics couvrent les profils, endpoints, listeners, logging, base de données, wallet, exécution et démonstration.
|
||||
|
||||
## Relations
|
||||
|
||||
- dépend de `ks-core` pour les erreurs structurées ;
|
||||
- alimente `ks-logging`, `ks-store`, `ks-onchain-transport`, `ks-pipeline`, `ks-wallet` et les applications ;
|
||||
- utilise [`../config/example.config.json`](../config/example.config.json) et [`../config/schema.config.json`](../config/schema.config.json) comme exemple utilisateur et contrat de schéma actifs.
|
||||
|
||||
## Statut
|
||||
|
||||
La configuration actuelle est fonctionnelle et validée, mais son format `0.4.8` reste monolithique. Le cadrage `0.5.0-pre.002` confirme que `0.5.1` séparera la configuration générale et le logging en documents et schémas distincts, introduira le namespace d’environnement `KS_*` et séparera les représentations source, runtime et publiques afin qu’aucun secret résolu ne soit exposé.
|
||||
|
||||
## Documents
|
||||
|
||||
- [Utilisation](USAGE.md)
|
||||
- [Travaux restants](TODO.md)
|
||||
- [Historique](CHANGELOG.md)
|
||||
- [Architecture](../docs/architecture/ARCHITECTURE.md)
|
||||
20
ks-config/TODO.md
Normal file
20
ks-config/TODO.md
Normal file
@@ -0,0 +1,20 @@
|
||||
<!-- file: ks-config/TODO.md -->
|
||||
<!-- version: 5 -->
|
||||
|
||||
# TODO — ks-config
|
||||
|
||||
## Série `0.5.x`
|
||||
|
||||
- [ ] `0.5.1` - séparer la configuration générale et le logging en documents et schémas JSON distincts.
|
||||
- [ ] `0.5.1` - rendre la sélection du profil logging indépendante du profil généraliste.
|
||||
- [ ] `0.5.1` - définir un propriétaire unique du contrat source logging et supprimer la conversion manuelle du desktop.
|
||||
- [ ] `0.5.1` - migrer toutes les variables d’environnement propres au projet vers le namespace `KS_*`.
|
||||
- [ ] `0.5.1` - appliquer les classes `KS_SECRET_*`, `KS_PUBLIC_*` et `KS_*` interne avec propagation de sensibilité aux valeurs composées.
|
||||
- [ ] `0.5.1` - séparer les représentations source, runtime résolue, publique et diagnostic.
|
||||
- [ ] `0.5.1` - interdire qu’un secret résolu soit sérialisé, loggé, inclus dans une erreur ou transmis via Tauri.
|
||||
- [ ] `0.5.1` - supprimer l’exposition frontend de `AppConfig` et `ProfileConfig` résolus complets.
|
||||
- [ ] Migration - fournir une table exhaustive des anciens noms d’environnement vers `KS_*` et une stratégie explicite pour le format `0.4.8`.
|
||||
- [ ] Contrat - maintenir l’identité entre chaque schéma embarqué et son fichier sous `config/`.
|
||||
- [ ] Tests - ajouter les tests d’API externe, de migration multi-fichiers et les canaris de non-divulgation.
|
||||
- [ ] Documentation - mettre à jour guides, exemples et `.env.example` seulement avec l’implémentation correspondante.
|
||||
- [ ] Intégration - coordonner la migration avec logging, transports, pipeline, scénarios et applications.
|
||||
143
ks-config/USAGE.md
Normal file
143
ks-config/USAGE.md
Normal file
@@ -0,0 +1,143 @@
|
||||
<!-- file: ks-config/USAGE.md -->
|
||||
<!-- version: 5 -->
|
||||
|
||||
# Utilisation de ks-config
|
||||
|
||||
## Chargement recommandé
|
||||
|
||||
```rust
|
||||
let config_result = ks_config::read_config_json_file_with_environment(
|
||||
std::path::Path::new("config/example.config.json"),
|
||||
std::path::Path::new("."),
|
||||
);
|
||||
let config = match config_result {
|
||||
Ok(value) => value,
|
||||
Err(error) => return Err(error),
|
||||
};
|
||||
let profile = match ks_config::active_profile(&config) {
|
||||
Ok(value) => value,
|
||||
Err(error) => return Err(error),
|
||||
};
|
||||
```
|
||||
|
||||
Cette fonction charge l’environnement du workspace, résout les placeholders puis applique successivement le schéma JSON, la désérialisation typée et les invariants métier.
|
||||
|
||||
## Chargement de l’environnement
|
||||
|
||||
```rust
|
||||
let report = match ks_config::load_workspace_environment(std::path::Path::new(".")) {
|
||||
Ok(value) => value,
|
||||
Err(error) => return Err(error),
|
||||
};
|
||||
|
||||
for path in report.loaded_files {
|
||||
println!("environment file: {}", path.display());
|
||||
}
|
||||
```
|
||||
|
||||
`EnvironmentLoadReport` indique les fichiers chargés. Les placeholders non résolus sans fallback restent visibles afin que la validation ou le consommateur puisse les signaler explicitement. Le format `0.4.8` accepte encore les anciens noms d’environnement ; la migration `0.5.1` imposera le namespace `KS_*`.
|
||||
|
||||
## Résolution explicite des placeholders
|
||||
|
||||
```rust
|
||||
let raw = r#"{"databaseUrl":"${KB_DATABASE_URL:-postgres://localhost/kb}"}"#;
|
||||
let resolved = ks_config::resolve_environment_placeholders(raw);
|
||||
|
||||
assert!(resolved.contains("databaseUrl"));
|
||||
```
|
||||
|
||||
Cette API retourne actuellement une chaîne résolue ordinaire et peut donc contenir des secrets issus de l’environnement. Elle doit rester strictement backend et ne doit pas être utilisée pour afficher, logger ou transmettre le JSON résolu. `0.5.1` remplacera cette frontière par une résolution conservant la classification de sensibilité.
|
||||
|
||||
## Validation et parsing
|
||||
|
||||
```rust
|
||||
if let Err(error) = ks_config::validate_config_json_schema(raw_json) {
|
||||
return Err(error);
|
||||
}
|
||||
let config = match ks_config::parse_config_json(raw_json) {
|
||||
Ok(value) => value,
|
||||
Err(error) => return Err(error),
|
||||
};
|
||||
if let Err(error) = ks_config::validate_config(&config) {
|
||||
return Err(error);
|
||||
}
|
||||
```
|
||||
|
||||
`parse_config_json` effectue déjà les deux validations ; les appels séparés servent aux outils de diagnostic.
|
||||
|
||||
## Sérialisation
|
||||
|
||||
```rust
|
||||
let compact = match ks_config::serialize_config_json(&config) {
|
||||
Ok(value) => value,
|
||||
Err(error) => return Err(error),
|
||||
};
|
||||
let pretty = match ks_config::serialize_config_json_pretty(&config) {
|
||||
Ok(value) => value,
|
||||
Err(error) => return Err(error),
|
||||
};
|
||||
|
||||
let write_result = std::fs::write("config/generated.config.json", pretty);
|
||||
if let Err(error) = write_result {
|
||||
return Err(ks_core::Error::new(
|
||||
"config_write_failed",
|
||||
format!("cannot write generated configuration: {error}"),
|
||||
));
|
||||
}
|
||||
```
|
||||
|
||||
La configuration est validée avant sérialisation.
|
||||
|
||||
## Schéma embarqué
|
||||
|
||||
```rust
|
||||
let schema_text = ks_config::config_json_schema_text();
|
||||
let schema_value = match ks_config::config_json_schema_value() {
|
||||
Ok(value) => value,
|
||||
Err(error) => return Err(error),
|
||||
};
|
||||
|
||||
let property_count = schema_value
|
||||
.get("properties")
|
||||
.and_then(serde_json::Value::as_object)
|
||||
.map_or(0, serde_json::Map::len);
|
||||
|
||||
println!("embedded schema bytes={}, properties={property_count}", schema_text.len());
|
||||
```
|
||||
|
||||
Le schéma actif est aussi disponible sous [`../config/schema.config.json`](../config/schema.config.json). Le fichier [`../config/example.config.json`](../config/example.config.json) fournit un exemple utilisateur complet.
|
||||
|
||||
## Sélection du profil actif
|
||||
|
||||
```rust
|
||||
let profile = match ks_config::active_profile(&config) {
|
||||
Ok(value) => value,
|
||||
Err(error) => return Err(error),
|
||||
};
|
||||
|
||||
println!("active profile: {}", profile.name);
|
||||
println!("http endpoints: {}", profile.solana.http_endpoints.len());
|
||||
println!("websocket endpoints: {}", profile.solana.ws_endpoints.len());
|
||||
```
|
||||
|
||||
## Types publics importants
|
||||
|
||||
- `AppConfig`, `ProfileConfig`, `AppSectionConfig` ;
|
||||
- `DatabaseConfig`, `PostgresConfig`, `SqliteConfig`, `DataConfig` ;
|
||||
- `SolanaConfig`, `HttpEndpointConfig`, `WsEndpointConfig`, `EndpointRoleConfig` ;
|
||||
- `ListenerConfig` et ses variantes ;
|
||||
- `LoggingConfig`, `LogTargetConfig`, `LogTargetFilterConfig` ;
|
||||
- `WalletConfig`, `ExecutionConfig`, `DemoConfig`.
|
||||
|
||||
## Erreurs et invariants
|
||||
|
||||
Les erreurs utilisent `ks_core::Error` avec un code stable. Les validations couvrent notamment l’unicité des profils, l’existence du profil actif, les URLs, les rôles d’endpoints, les limites d’exécution, les routes de logging et les contraintes wallet.
|
||||
|
||||
## Tests instructifs
|
||||
|
||||
Les tests `example_config_validates_against_schema`, `example_config_parses_and_resolves_active_profile` et `example_config_routes_global_and_operational_crate_files` démontrent le contrat complet de l’exemple actif. Les tests `parser_rejects_*` et `schema_rejects_*` documentent les invariants refusés.
|
||||
|
||||
## Limites
|
||||
|
||||
- format JSON uniquement ;
|
||||
- la crate valide les références et paramètres, mais n’ouvre aucune connexion externe.
|
||||
95
ks-config/src/environment.rs
Normal file
95
ks-config/src/environment.rs
Normal file
@@ -0,0 +1,95 @@
|
||||
// file: ks-config/src/environment.rs
|
||||
// version: 4
|
||||
|
||||
//! Environment-file loading and configuration placeholder resolution.
|
||||
|
||||
/// Result of loading one optional workspace environment file.
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct EnvironmentLoadReport {
|
||||
/// Explicit or default environment file that was loaded.
|
||||
pub loaded_path: std::option::Option<std::path::PathBuf>,
|
||||
}
|
||||
|
||||
/// Loads the selected environment file without overriding process variables.
|
||||
///
|
||||
/// Resolution order is: existing process environment, selected `.env`, then
|
||||
/// fallback text declared with `${NAME:-fallback}` placeholders.
|
||||
pub fn load_workspace_environment(
|
||||
workspace_root: &std::path::Path,
|
||||
) -> ks_core::Result<EnvironmentLoadReport> {
|
||||
let explicit_path = std::env::var("KB_ENV_FILE").ok();
|
||||
let selected_path = match explicit_path {
|
||||
std::option::Option::Some(path) if !path.trim().is_empty() => {
|
||||
let candidate = std::path::PathBuf::from(path);
|
||||
if candidate.is_absolute() { candidate } else { workspace_root.join(candidate) }
|
||||
},
|
||||
_ => workspace_root.join(".env"),
|
||||
};
|
||||
if !selected_path.exists() {
|
||||
return std::result::Result::Ok(EnvironmentLoadReport { loaded_path: None });
|
||||
}
|
||||
return match dotenvy::from_path(&selected_path) {
|
||||
std::result::Result::Ok(()) => std::result::Result::Ok(EnvironmentLoadReport {
|
||||
loaded_path: std::option::Option::Some(selected_path),
|
||||
}),
|
||||
std::result::Result::Err(error) => std::result::Result::Err(ks_core::Error::new(
|
||||
"config_env_file_load_failed",
|
||||
format!("{}: {error}", selected_path.display()),
|
||||
)),
|
||||
};
|
||||
}
|
||||
|
||||
/// Resolves `${NAME}` and `${NAME:-fallback}` placeholders in arbitrary text.
|
||||
/// Missing variables without fallbacks are preserved for lazy consumers.
|
||||
pub fn resolve_environment_placeholders(raw: &str) -> std::string::String {
|
||||
let mut output = std::string::String::with_capacity(raw.len());
|
||||
let bytes = raw.as_bytes();
|
||||
let mut index = 0_usize;
|
||||
while index < bytes.len() {
|
||||
if bytes[index] == b'$' && index + 1 < bytes.len() && bytes[index + 1] == b'{' {
|
||||
let start = index;
|
||||
let mut end = index + 2;
|
||||
while end < bytes.len() && bytes[end] != b'}' {
|
||||
end += 1;
|
||||
}
|
||||
if end < bytes.len() {
|
||||
let expression = &raw[index + 2..end];
|
||||
let (name, fallback) = match expression.split_once(":-") {
|
||||
std::option::Option::Some((name, fallback)) => {
|
||||
(name, std::option::Option::Some(fallback))
|
||||
},
|
||||
std::option::Option::None => (expression, std::option::Option::None),
|
||||
};
|
||||
let resolved = std::env::var(name)
|
||||
.ok()
|
||||
.or_else(|| return fallback.map(|value| return value.to_string()));
|
||||
match resolved {
|
||||
std::option::Option::Some(value) => output.push_str(&value),
|
||||
std::option::Option::None => output.push_str(&raw[start..=end]),
|
||||
}
|
||||
index = end + 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
output.push(bytes[index] as char);
|
||||
index += 1;
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn fallback_is_used_when_variable_is_absent() {
|
||||
let resolved =
|
||||
super::resolve_environment_placeholders("${KB_CONFIG_TEST_MISSING:-fallback}");
|
||||
assert_eq!(resolved, "fallback");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unresolved_required_placeholder_is_preserved() {
|
||||
let resolved =
|
||||
super::resolve_environment_placeholders("prefix-${KB_CONFIG_TEST_MISSING}-suffix");
|
||||
assert_eq!(resolved, "prefix-${KB_CONFIG_TEST_MISSING}-suffix");
|
||||
}
|
||||
}
|
||||
79
ks-config/src/lib.rs
Normal file
79
ks-config/src/lib.rs
Normal file
@@ -0,0 +1,79 @@
|
||||
// file: ks-config/src/lib.rs
|
||||
// version: 5
|
||||
|
||||
//! Khadhroony Bot3 workspace configuration contract and loading helpers.
|
||||
#![warn(missing_docs)]
|
||||
#![deny(unreachable_pub)]
|
||||
#![forbid(unsafe_code)]
|
||||
|
||||
mod environment;
|
||||
mod settings;
|
||||
|
||||
/// Exposes the environment loading report.
|
||||
pub use self::environment::EnvironmentLoadReport;
|
||||
/// Exposes workspace environment-file loading.
|
||||
pub use self::environment::load_workspace_environment;
|
||||
/// Exposes environment placeholder resolution.
|
||||
pub use self::environment::resolve_environment_placeholders;
|
||||
/// Exposes the account listener configuration type.
|
||||
pub use self::settings::AccountListenerConfig;
|
||||
/// Exposes the root application configuration type.
|
||||
pub use self::settings::AppConfig;
|
||||
/// Exposes the application section configuration type.
|
||||
pub use self::settings::AppSectionConfig;
|
||||
/// Exposes the local data configuration type.
|
||||
pub use self::settings::DataConfig;
|
||||
/// Exposes the database configuration type.
|
||||
pub use self::settings::DatabaseConfig;
|
||||
/// Exposes the demo application configuration type.
|
||||
pub use self::settings::DemoConfig;
|
||||
/// Exposes the endpoint role configuration type.
|
||||
pub use self::settings::EndpointRoleConfig;
|
||||
/// Exposes the execution configuration type.
|
||||
pub use self::settings::ExecutionConfig;
|
||||
/// Exposes the HTTP endpoint configuration type.
|
||||
pub use self::settings::HttpEndpointConfig;
|
||||
/// Exposes the listener configuration type.
|
||||
pub use self::settings::ListenerConfig;
|
||||
/// Exposes the log listener configuration type.
|
||||
pub use self::settings::LogListenerConfig;
|
||||
/// Exposes the logging target configuration type.
|
||||
pub use self::settings::LogTargetConfig;
|
||||
/// Exposes the logging target filter configuration type.
|
||||
pub use self::settings::LogTargetFilterConfig;
|
||||
/// Exposes the logging configuration type.
|
||||
pub use self::settings::LoggingConfig;
|
||||
/// Exposes the PostgreSQL configuration type.
|
||||
pub use self::settings::PostgresConfig;
|
||||
/// Exposes the profile configuration type.
|
||||
pub use self::settings::ProfileConfig;
|
||||
/// Exposes the program listener configuration type.
|
||||
pub use self::settings::ProgramListenerConfig;
|
||||
/// Exposes the Solana configuration type.
|
||||
pub use self::settings::SolanaConfig;
|
||||
/// Exposes the SQLite configuration type.
|
||||
pub use self::settings::SqliteConfig;
|
||||
/// Exposes the wallet configuration type.
|
||||
pub use self::settings::WalletConfig;
|
||||
/// Exposes the WebSocket endpoint configuration type.
|
||||
pub use self::settings::WsEndpointConfig;
|
||||
/// Exposes the active profile resolver.
|
||||
pub use self::settings::active_profile;
|
||||
/// Exposes the embedded JSON Schema text.
|
||||
pub use self::settings::config_json_schema_text;
|
||||
/// Exposes the embedded JSON Schema value parser.
|
||||
pub use self::settings::config_json_schema_value;
|
||||
/// Exposes the configuration parser from a JSON string.
|
||||
pub use self::settings::parse_config_json;
|
||||
/// Exposes the configuration loader from a filesystem path.
|
||||
pub use self::settings::read_config_json_file;
|
||||
/// Exposes configuration loading with workspace environment resolution.
|
||||
pub use self::settings::read_config_json_file_with_environment;
|
||||
/// Exposes the compact JSON serializer for configuration values.
|
||||
pub use self::settings::serialize_config_json;
|
||||
/// Exposes the pretty JSON serializer for configuration values.
|
||||
pub use self::settings::serialize_config_json_pretty;
|
||||
/// Exposes the typed configuration validator.
|
||||
pub use self::settings::validate_config;
|
||||
/// Exposes the JSON Schema validator for raw JSON configuration.
|
||||
pub use self::settings::validate_config_json_schema;
|
||||
1600
ks-config/src/settings.rs
Normal file
1600
ks-config/src/settings.rs
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user