Files
rpg-companion-sillytavern/src/utils/migration.js
T

115 lines
3.9 KiB
JavaScript

/**
* Inventory Migration Module
* Handles conversion from v1 (string) to v2 (structured) inventory format
*/
// Type imports
/** @typedef {import('../types/inventory.js').InventoryV1} InventoryV1 */
/** @typedef {import('../types/inventory.js').InventoryV2} InventoryV2 */
/** @typedef {import('../types/inventory.js').MigrationResult} MigrationResult */
/**
* Default v2 inventory structure for new/empty inventories
* @type {InventoryV2}
*/
const DEFAULT_INVENTORY_V2 = {
version: 2,
onPerson: "None",
clothing: "None",
stored: {},
assets: "None"
};
/**
* Migrates inventory data from v1 (string) to v2 (structured) format.
* Handles all edge cases: null, undefined, "None", already-migrated data.
*
* @param {InventoryV1 | InventoryV2 | null | undefined} inventory - Inventory data to migrate
* @returns {MigrationResult} Migration result with v2 inventory and metadata
*/
export function migrateInventory(inventory) {
// Case 1: v2 format missing version property (parser output)
// Parser returns v2 structure but without the version tag
if (inventory && typeof inventory === 'object' &&
'onPerson' in inventory && 'clothing' in inventory &&
'stored' in inventory && 'assets' in inventory &&
!('version' in inventory)) {
// console.log('[RPG Companion Migration] v2 inventory missing version tag, adding it');
return {
inventory: {
version: 2,
...inventory
},
migrated: true,
source: 'parser-output'
};
}
// Case 2: Already v2 format (has version property and is an object)
if (inventory && typeof inventory === 'object' && inventory.version === 2) {
// Check if clothing field exists (v2.1 upgrade)
if (!inventory.hasOwnProperty('clothing')) {
// console.log('[RPG Companion Migration] Upgrading v2 inventory to v2.1 (adding clothing field)');
inventory.clothing = "None";
return {
inventory: inventory,
migrated: true,
source: 'v2-upgrade'
};
}
// console.log('[RPG Companion Migration] Inventory already v2, no migration needed');
return {
inventory: inventory,
migrated: false,
source: 'v2'
};
}
// Case 3: null or undefined → use defaults
if (inventory === null || inventory === undefined) {
// console.log('[RPG Companion Migration] Inventory is null/undefined, using defaults');
return {
inventory: { ...DEFAULT_INVENTORY_V2 },
migrated: true,
source: 'null'
};
}
// Case 4: v1 string format → migrate to v2
if (typeof inventory === 'string') {
// Check if it's an empty/default string
const trimmed = inventory.trim();
if (trimmed === '' || trimmed.toLowerCase() === 'none') {
// console.log('[RPG Companion Migration] Inventory is empty/None, using defaults');
return {
inventory: { ...DEFAULT_INVENTORY_V2 },
migrated: true,
source: 'v1'
};
}
// Non-empty v1 string → migrate to v2.onPerson
// console.log('[RPG Companion Migration] Migrating v1 string to v2.onPerson:', inventory);
return {
inventory: {
version: 2,
onPerson: inventory,
clothing: "None",
stored: {},
assets: "None"
},
migrated: true,
source: 'v1'
};
}
// Case 4: Unknown format (malformed object, number, etc.) → use defaults
console.warn('[RPG Companion Migration] Unknown inventory format, using defaults:', inventory);
return {
inventory: { ...DEFAULT_INVENTORY_V2 },
migrated: true,
source: 'default'
};
}