Skip to content

verschuls/YamlFlow

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

20 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

YamlFlow

Lightweight wrapper for ConfigLib with centralized config management. Java 21

Installation

Maven

<repositories>
    <repository>
        <id>jitpack.io</id>
        <url>https://jitpack.io</url>
    </repository>
</repositories>

<dependency>
    <groupId>com.github.verschuls</groupId>
    <artifactId>YamlFlow</artifactId>
    <version>v1.2.4</version>
</dependency>

Gradle

repositories {
    maven { url 'https://jitpack.io' }
}

dependencies {
    implementation 'com.github.verschuls:YamlFlow:v1.2.4'
}

Features

  • Hash-based reloading - Only reloads when file content changes
  • Async initialization - Non-blocking config loading with CompletableFuture
  • Reload callbacks - React to config changes
  • Thread-safe - All operations are properly synchronized
  • Bulk loading - Load multiple configs from a directory
  • Config versioning - Automatic backup and migration on version mismatch

CM - Single Config Management

Use CM for named config files (settings.yml, messages.yml, etc.)

public class ServerConfig extends BaseConfig<ServerConfig.Data> {
    public ServerConfig(Path dir) {
        super(dir, "server", Data.class);
    }

    @Header("Server Configuration")
    @Footer("End of config")
    public static class Data extends BaseData {
        public String host = "localhost";
        public int port = 8080;
    }
}

// Register
CM.register(new ServerConfig(Path.of("./config")));

// Wait for init
CM.onInit(ServerConfig.class).thenAccept(data -> {
    System.out.println("Server: " + data.host + ":" + data.port);
});

// Get data (after init)
ServerConfig.Data data = CM.get(ServerConfig.class);

// Reload & callbacks
CM.reload(ServerConfig.class);
CM.onReload(ServerConfig.class, data -> System.out.println("Reloaded!"));

Config Versioning

Add automatic version tracking and backup on version mismatch using the @CVersion annotation. Works with both CM and CMI.

public class VersionedConfig extends BaseConfig<VersionedConfig.Data> {
    public VersionedConfig(Path dir) {
        super(dir, "config", Data.class);
    }

    @CVersion("1.0.0")
    public static class Data extends BaseData {
        public String setting = "default";
    }
}

Behavior:

  • On load, the file's version field is compared against the @CVersion value
  • If versions don't match, the old config is backed up to old/config-v1.0.0-xxxx.yml
  • The config is then updated with the new version and default values for new fields

Custom backup directory:

@CVersion(value = "1.0.0", backupDir = "backups")
public static class Data extends BaseData {
    // backups will go to backups/config-vX.X.X-xxxx.yml
}

Custom version comparison:

// Set custom comparator (called once at startup)
CM.setVersionComparator((fileVersion, configVersion) ->
    fileVersion.equals(configVersion)  // return true = versions match, skip backup
);

CMI - Bulk Config Loading

Use CMI for loading multiple similar configs from a directory (players/, kits/, etc.)

@Configuration
public class PlayerData extends BaseData {
    public String name = "Unknown";
    public int level = 1;
}

// Using the builder pattern
CMI<String, PlayerData> players = CMI.newBuilder(
        Path.of("./players"),
        PlayerData.class,
        CIdentifier.fileName()
    )
    .filter(CFilter.underScores())
    .inputNulls(true)
    .build();

// Access configs
Optional<PlayerData> player = players.get("steve");
HashMap<String, ConfigInfo<PlayerData>> all = players.get();

// Access config with path info
Optional<ConfigInfo<PlayerData>> info = players.getInfo("steve");
info.ifPresent(i -> {
    System.out.println("Path: " + i.getPath());
    System.out.println("Name: " + i.getData().name);
});

// Create & save
ConfigInfo<PlayerData> newPlayer = players.create("alex", "alex");
newPlayer.getData().name = "Alex";
players.save("alex", newPlayer.getData());

// Reload
players.reload();
players.onReload(all -> System.out.println("Reloaded " + all.size() + " players"));

CMI also supports versioning with @CVersion:

@Configuration
@CVersion(value = "2.0", backupDir = "old_players")
public class PlayerData extends BaseData {
    public String name = "Unknown";
    public int level = 1;
    public int xp = 0; // new field in v2.0
}

// Custom version comparator for this CMI instance
CMI<String, PlayerData> players = CMI.newBuilder(Path.of("./players"), PlayerData.class, CIdentifier.fileName())
    .setVersionCompare((fileVersion, configVersion) -> fileVersion.equals(configVersion))
    .build();

Builder Options

Method Description
filter(CFilter) Exclude files from loading
setVersionCompare(VersionCompare) Custom version comparator (default: VersionCompare.basic())
inputNulls(boolean) Allow null values from YAML
outputNulls(boolean) Write null values to YAML
acceptNulls(boolean) Shorthand for both inputNulls and outputNulls
addSerializer(Class, Serializer) Custom type serializer
addSerializerFactory(Class, Function) Context-aware serializer factory
setFieldFilter(Predicate<Field>) Control which fields are serialized
setNameFormatter(NameFormatter) Custom field-to-YAML-key naming

CIdentifier - Key Strategies

Control how configs are identified in CMI:

// File name as key: "player.yml" -> "player"
CIdentifier.fileName()

// Parse file name as UUID: "550e8400-e29b-...yml" -> UUID
CIdentifier.fileNameUUID()

// Auto-increment IDs: 0, 1, 2, ...
CIdentifier.simpleID(new AtomicInteger())

// Custom logic
(file, config) -> config.customId

CFilter - File Filtering

Filter which files to load:

// Load all files
CFilter.none()

// Skip files like "_template_.yml"
CFilter.underScores()

// Custom filter (return true to exclude)
(file, config) -> file.getName().startsWith("backup")

Header & Footer Annotations

Add headers/footers to generated YAML files:

@Header("=== My Config ===\nEdit with care")
@Footer("Generated by YamlFlow")
public static class Data extends BaseData {
    public String value = "default";
}

Output:

# === My Config ===
# Edit with care

value: default

# Generated by YamlFlow

Coming Soon

  • Async CMI - Non-blocking bulk config loading?
  • Optimizations - Performance improvements?
  • CM Properties - Builder pattern for BaseConfig
  • ...and more

About

Lightweight wrapper for configlib-yaml with centralized config management

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages