feat(inventory): implement v2 data structure and JSDoc types (Epic 7.1)
Create structured inventory system with categorized storage:
- Add JSDoc type definitions (InventoryV2, InventoryV1, MigrationResult)
- Implement migration utility for v1 → v2 conversion
- Update state.js with v2 inventory structure and feature flag
- Update config.js to match new inventory defaults
Changes:
- NEW: src/types/inventory.js (30 lines) - Type definitions
- NEW: src/utils/migration.js (84 lines) - Migration logic
- MODIFIED: src/core/state.js - v2 inventory + FEATURE_FLAGS
- MODIFIED: src/core/config.js - v2 inventory defaults
Inventory v2 structure:
{
version: 2,
onPerson: "Sword, 3x Potions", // Plaintext string
stored: {
"Home": "Clothes, Tools", // Location → items
"Bank": "Gold, Documents"
},
assets: "Motorcycle, House" // Plaintext string
}
Migration handles all edge cases:
- v1 string → v2.onPerson
- null/undefined → v2 defaults
- "None" → v2 defaults
- Already v2 → no changes
Context overhead: +40 chars (~5% increase) for organized multi-location storage
Part of Epic 7: New Inventory System
Implements: docs/IMPLEMENTATION_PLAN.md Epic 7.1
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
* 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",
|
||||
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: Already v2 format (has version property and is an object)
|
||||
if (inventory && typeof inventory === 'object' && inventory.version === 2) {
|
||||
// console.log('[RPG Companion Migration] Inventory already v2, no migration needed');
|
||||
return {
|
||||
inventory: inventory,
|
||||
migrated: false,
|
||||
source: 'v2'
|
||||
};
|
||||
}
|
||||
|
||||
// Case 2: 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 3: 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,
|
||||
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'
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user