Figment
Figment copied to clipboard
Best way to support an "extends other config" field
@SergioBenitez
Many tools and their config files support the concept of extending additional config files through a field within the file, with the values being a relative file system path (extends: './other/config.yml'
) or URL (extends: 'https://domain.com/config.yml'
). With this approach, the extends
file is applied before the file doing the extending, so that the current document can override or merge when necessary. This is pretty great for composibility and reusability.
However, this seems to be extremely difficult in Figment, and I'm curious on the best way to approach it. The current problems are:
- We can't use
merge()
orjoin()
because we don't know what file to extend until after the config has been parsed and extracted. - We can't use a provider since it doesn't have access to the currently parsed config from the previous provider.
- We can't use a profile because it still needs a way to be resolved.
I have a working solution to this problem but it requires resolving and parsing the config twice, as demonstrated here: https://github.com/moonrepo/moon/pull/142/files#diff-752c2babea244e138a59a074967c9c3bb0faf51bf0a413ac4128505e2b58fb7fR146 The second figment extraction contains an additional merge()
for the extending file (which is requested via URL).
In an ideal world, something like this would be pretty great.
Figment::from(Serialized::defaults(WorkspaceConfig::default()))
.merge(Yaml::file(&path))
.merge_first(Yaml::from_field("extends"))
.extract()
Since a Figment
is itself a Provider
, I wonder if we need any special support for this. How does this look?
let mut fig = Figment::from(Yaml::file(path));
if let Ok(path) = layer.find_value("extends").map(|v| v.as_str()) {
fig = Figment::from(Yaml::file(path)).merge(fig);
}
fig.extract()
If you want path
to be relative to where it was declared, then use the value.tag()
to retrieve the location via Figment.get_metadata()
and make the path relative to it using figment::util::diff_paths.
Closing due to inactivity.