-
Notifications
You must be signed in to change notification settings - Fork 0
Versioning
As your addon evolves, the structure of your saved variables may change. New settings may be added, existing settings may be renamed, data may be reorganized, or old values may need to be removed.
LibSavedVars uses version numbers to track changes to saved data and determine when a migration is required.
Versioning allows your addon to update existing user data automatically without requiring users to delete their SavedVariables files.
Saved variables persist across addon updates. This means users may have data created by an older version of your addon.
For example, version 1 of an addon may store:
{
enabled = true
}Later, version 2 reorganizes the data:
{
general = {
enabled = true
}
}Without version tracking, the addon cannot determine whether the existing data needs to be updated.
Versioning provides a way to identify the format of stored data and apply the required changes.
Every saved variables creation function includes a version parameter.
Example:
local settings = LibSavedVars:NewAccountWide(
"MyAddonSavedVariables",
2,
nil,
defaults
)The version number represents the current format of your saved data.
When LibSavedVars loads the saved variables, it compares:
- The version stored with the user's data.
- The version specified by the addon.
When an addon loads:
- LibSavedVars reads the saved data version.
- The current addon version is compared against the stored version.
- If the versions match, no update is required.
- If the stored version is older, migrations are executed.
- After successful migration, the saved data version is updated.
Example:
| Stored Version | Addon Version | Result |
|---|---|---|
| 1 | 1 | No migration |
| 1 | 2 | Run version 2 migration |
| 2 | 5 | Run migrations 3, 4, and 5 |
| 5 | 5 | No migration |
Increase the version only when existing saved data must change.
Examples that require a version increase:
- Renaming a setting.
- Moving a setting to a new location.
- Changing the data format.
- Combining multiple settings.
- Splitting one setting into multiple settings.
- Removing obsolete data.
- Moving data between account-wide and character storage.
Example:
Before:
settings.opacityAfter:
settings.display.opacityBecause existing data must be moved, the saved variable version should increase.
Not every addon update requires a new version.
Adding a new default value usually does not require a migration.
Version 1:
local defaults = {
enabled = true,
}Version 2:
local defaults = {
enabled = true,
showTooltips = true,
}Existing users automatically receive:
settings.showTooltips == truebecause the default value is supplied when no saved value exists.
No migration is necessary.
Defaults and versioning solve different problems.
| Feature | Purpose |
|---|---|
| Defaults | Provides values for settings that do not exist. |
| Versioning | Detects when existing saved data must be changed. |
A useful rule:
- New setting? Add it to the defaults table.
- Changed existing data? Increase the version and migrate.
Each migration is associated with the version it creates.
Example:
settings:Migrate(2, function(savedVars)
-- Convert version 1 data to version 2
end)
settings:Migrate(3, function(savedVars)
-- Convert version 2 data to version 3
end)A user upgrading directly from version 1 to version 3 runs:
- Version 2 migration.
- Version 3 migration.
Each migration should only handle one version change.
Migrations execute in ascending version order.
Example:
settings:Migrate(2, migrateToVersion2)
settings:Migrate(3, migrateToVersion3)
settings:Migrate(4, migrateToVersion4)Upgrade path:
Version 1
|
v
Migration 2
|
v
Migration 3
|
v
Migration 4
|
v
Version 4
This allows users to upgrade from any previous release without skipping required changes.
Once an addon has released a migration, do not remove or rewrite it.
A user may upgrade from an old version directly to the newest version.
Example:
Version 1
|
v
Version 2 migration
|
v
Version 3 migration
|
v
Current version
Removing the version 2 migration could prevent old users from upgrading correctly.
Each migration should perform one logical update.
Good:
settings:Migrate(2, function(savedVars)
savedVars.newName = savedVars.oldName
savedVars.oldName = nil
end)Avoid combining unrelated changes:
settings:Migrate(2, function(savedVars)
-- rename settings
-- restructure tables
-- convert formats
-- remove old data
end)Do not test only new installations.
Create saved variable data from older addon versions and verify that upgrading produces the expected result.
Test cases should include:
- Fresh installation.
- One-version upgrade.
- Multiple-version upgrade.
- Missing optional settings.
- Existing customized values.
Complete example:
local settings = LibSavedVars:NewAccountWide(
"MyAddonSavedVariables",
3,
nil,
defaults
)
settings:Migrate(2, function(savedVars)
savedVars.general = savedVars.general or {}
savedVars.general.enabled = savedVars.enabled
savedVars.enabled = nil
end)
settings:Migrate(3, function(savedVars)
savedVars.general.scale =
savedVars.scale or 1.0
savedVars.scale = nil
end)A user upgrading from version 1 receives both updates automatically.
Versioning allows LibSavedVars addons to safely evolve their saved data structure over time.
Use version numbers to answer:
"Does this user's saved data need to be updated?"
Use migrations to answer:
"How should the saved data be updated?"
Together, versioning and migrations allow addons to add features, reorganize settings, and improve their design while preserving user preferences.