-
Notifications
You must be signed in to change notification settings - Fork 0
Migration Helpers
In LibSavedVars, migration helpers are convenience functions that simplify common saved-variable transformations. They are intended for cases where a normal Migrate(version, callback) function would require repetitive or error-prone table manipulation.
A migration helper usually performs a specific, well-defined operation such as:
Creating a missing path.
Moving a value from one location to another.
Copying data between locations.
Removing obsolete settings.
Moving data between character and account-wide storage.
They are especially useful when an addon has been released for a while and its saved variable structure has changed several times.
Without helpers, a migration often looks like this:
settings:Migrate(2, function(savedVars)
savedVars.ui = savedVars.ui or {}
savedVars.ui.scale = savedVars.scale
savedVars.scale = nil
end)
This works, but every migration author has to correctly handle:
Missing intermediate tables.
Nil values.
Existing destination values.
Removing old data.
Avoiding accidental overwrites.
A helper can encapsulate these rules:
settings:Migrate(2, function(savedVars)
protected.MovePath(
savedVars,
{"scale"},
{"ui", "scale"}
)
end)
The migration becomes clearer: move scale into ui.scale.
Many migrations need to create a table hierarchy before assigning a value.
Example:
Before:
{
enabled = true
}
After:
{
general = {
enabled = true
}
}
A helper can create the missing path:
CreatePath(savedVars, "general")
instead of requiring:
savedVars.general = savedVars.general or {}
at every step.
A move operation copies a value to a new location and removes the old value.
Example:
Version 1:
settings.opacity
Version 2:
settings.ui.opacity
Migration:
Move(
savedVars,
"opacity",
"ui.opacity"
)
Result:
Before:
{
opacity = 0.8
}
After:
{
ui = {
opacity = 0.8
}
}
Move helpers are useful for:
Renaming settings.
Reorganizing configuration tables.
Consolidating settings.
Sometimes you want to preserve the old value while creating a new one.
Example:
Version 1:
settings.color
Version 2 adds:
settings.primaryColor
A copy migration:
Copy(
savedVars,
"color",
"primaryColor"
)
Result:
{
color = "red",
primaryColor = "red"
}
This is useful when the old value may still be needed for compatibility.
Old settings can accumulate over multiple releases.
Example:
{
enabled = true,
oldDebug = false
}
If oldDebug is no longer used:
Remove(
savedVars,
"oldDebug"
)
Result:
{
enabled = true
}
Removing obsolete values keeps SavedVariables clean.
One of the more advanced uses of LibSavedVars is changing where data is stored.
For example, an addon may originally use account-wide settings:
Account
└── Settings
└── scale = 1.0
Later, the addon adds per-character settings:
Account
├── Character A
│ └── scale = 1.0
└── Character B
└── scale = 1.2
A migration helper can move the existing account value into the character storage when the user changes modes.
The reverse is also possible:
Character Settings → Account Settings
This avoids forcing users to manually recreate their configuration.
Good migration helpers should:
A migration should be safe if the source value does not exist.
Example:
Move("oldName", "newName")
should do nothing if oldName is already gone.
A helper should generally avoid overwriting existing data unless explicitly requested.
Example:
savedVars.newValue = savedVars.oldValue
could destroy a user's existing newValue.
A safer helper can check:
if savedVars.newValue == nil then
savedVars.newValue = savedVars.oldValue
end
Helpers do not replace versioning.
The pattern remains:
settings:Migrate(3, function(savedVars)
Move(
savedVars,
"oldSetting",
"newSetting"
)
end)
The version determines when the helper runs.
The helper determines what changes.
A custom migration function is usually better when:
The transformation is complex.
Several values must be calculated together.
Data formats change significantly.
Validation is required.
Example:
settings:Migrate(5, function(savedVars)
savedVars.position = {
x = savedVars.oldX * 2,
y = savedVars.oldY * 2,
}
end)
A helper would not make this clearer.
Migration helpers are building blocks for common saved-variable changes. They reduce boilerplate and make migrations easier to read and maintain.
Use them for:
| Task | Recommended Approach |
|---|---|
| Rename a setting | Move helper |
| Move a setting into a new table | Move + CreatePath |
| Duplicate a setting | Copy helper |
| Delete old data | Remove helper |
| Change storage model | Account/Character migration helper |
| Complex conversion | Custom migration callback |
For small addons, Migrate() with a custom callback is usually enough. For larger addons with many releases, migration helpers provide a safer and more maintainable upgrade path.