Compare commits

...
Author SHA1 Message Date
legop3 d36ea4f672 Merge pull request #31 from legop3/REFACTOR-docking-undocking-serverside
Container image / image (push) Failing after 49s
Refactor docking undocking serverside
2026-10-02 23:23:23 -04:00
legop3 4be6e6c9a2 slop 2026-10-02 23:18:41 -04:00
legop3 c71267873a micrationslop
Container image / image (push) Failing after 56s
2026-10-01 02:33:56 -04:00
2 changed files with 30 additions and 1 deletions
+29 -1
View File
@@ -1,6 +1,6 @@
// Configuration Database Migrations
// Purpose: Applies ordered, transactional schema changes to the configuration and administration database.
// Scope: Owns database structure only; configuration-document evolution belongs to the ordered definition and validation.
// Scope: Upgrades database structure and stored configuration documents before current-schema validation.
const migrations = [
{
version: 1,
@@ -84,6 +84,34 @@ const migrations = [
`).run();
},
},
{
version: 4,
run(db) {
const rows = db.prepare('SELECT id, config_json FROM configuration_revisions').all();
const update = db.prepare('UPDATE configuration_revisions SET config_json = ? WHERE id = ?');
// Upgrade history as well as the active revision so a settings rollback
// cannot reintroduce fields rejected by the new Automations schema.
for (const row of rows) {
const config = JSON.parse(row.config_json);
let changed = false;
for (const item of config.homeAssistantActivities?.items || []) {
const hasAction = Object.hasOwn(item, 'idleAction');
const hasValue = Object.hasOwn(item, 'idleValue');
if (!hasAction && !hasValue) continue;
item.automations ??= {};
item.automations.idle ??= {};
// Preserve any explicitly saved new-format setting when both formats
// exist, including an empty text value used to clear an entity.
if (hasAction && !Object.hasOwn(item.automations.idle, 'action')) item.automations.idle.action = item.idleAction;
if (hasValue && !Object.hasOwn(item.automations.idle, 'value')) item.automations.idle.value = item.idleValue;
delete item.idleAction;
delete item.idleValue;
changed = true;
}
if (changed) update.run(JSON.stringify(config), row.id);
}
},
},
];
function applySchemaMigrations(db) {
@@ -109,6 +109,7 @@ async function copyDurableTree(sourceDir, destinationDir, relativeDir = '') {
const relativePath = path.join(relativeDir, entry.name);
if (!relativeDir && EXCLUDED_TOP_LEVEL_NAMES.has(entry.name)) continue;
if (!relativeDir && DATABASE_FILES.has(entry.name)) continue;
if (relativePath === path.join('rover-learning', 'recordings')) continue;
if (entry.isSymbolicLink()) throw new Error(`Backup cannot include symbolic link: ${relativePath}`);
if (entry.isDirectory()) {
skipped.push(...await copyDurableTree(sourceDir, destinationDir, relativePath));