Files
ToldoConjunto/skills/toldo-offline-export-import/SKILL.md

4.5 KiB

Agent Skill: toldo-offline-export-import

Metadata

name: toldo-offline-export-import
description: Exportar/importar JSON versionado, migraciones de esquema, validación e integridad para uso offline/APK. Funciona sin red.

When to use

Use this skill when:

  • Implementing export functionality
  • Implementing import functionality
  • Handling schema migrations
  • Versioning data formats
  • Ensuring data portability between devices

Export Format (Versioned JSON)

interface ExportData {
  schemaVersion: number;      // Database/schema version
  appVersion: string;        // App version
  exportedAt: string;        // ISO 8601 timestamp
  data: {
    productores: Productor[];
    productos: Producto[];
    movimientosInventario: MovimientoInventario[];
    ventas: Venta[];
    ventaLineas: VentaLinea[];
    gastos: Gasto[];
    ajustes: Ajuste[];
    cuadres: CuadreCaja[];
  };
}

Export Requirements

  • Include all entities
  • Use current schemaVersion
  • Include appVersion
  • Include exportedAt timestamp
  • Pretty print or compact JSON (both fine)
  • Filename suggestion: toldo-export-YYYY-MM-DD-HHMMSS.json
  • Works offline (no network calls)

Import Requirements

  • Validate JSON structure
  • Check schemaVersion compatibility
  • Migrate data if schemaVersion is older (supported migration path)
  • Reject if schemaVersion is newer and no migration path (with clear message)
  • Validate required fields
  • Handle errors gracefully with user-friendly messages
  • Option to backup current data before import? (recommended)
  • Works offline

Migration Strategy

function migrateExport(exportData: ExportData): ExportData {
  let data = { ...exportData };
  
  // Migrate from older versions
  while (data.schemaVersion < CURRENT_SCHEMA_VERSION) {
    data = migrateToNextVersion(data);
  }
  
  if (data.schemaVersion > CURRENT_SCHEMA_VERSION) {
    throw new Error(
      `Incompatible schema version: ${data.schemaVersion}. ` +
      `Current app supports up to ${CURRENT_SCHEMA_VERSION}. ` +
      `Please update the app.`
    );
  }
  
  return data;
}

function migrateToNextVersion(data: ExportData): ExportData {
  // Implement version-specific migrations
  // Example: add new fields with defaults
  switch (data.schemaVersion) {
    case 1:
      // migrate v1 -> v2
      return { ...data, schemaVersion: 2, data: migratedData };
    default:
      throw new Error('Unknown schema version');
  }
}

Validation

function validateExport(data: unknown): data is ExportData {
  // Check structure
  if (!isObject(data)) throw new Error('Invalid export format');
  if (typeof data.schemaVersion !== 'number') throw new Error('Missing schemaVersion');
  if (typeof data.appVersion !== 'string') throw new Error('Missing appVersion');
  if (!data.exportedAt) throw new Error('Missing exportedAt');
  if (!isObject(data.data)) throw new Error('Missing data');
  
  // Validate data arrays exist
  const required = ['productores', 'productos', 'ventas', 'gastos', ...];
  for (const key of required) {
    if (!Array.isArray(data.data[key])) throw new Error(`Missing or invalid ${key}`);
  }
  
  return true;
}

Usage in Capacitor

For APK/native, can use:

  • @capacitor/filesystem to save/load files
  • Web File API as fallback
  • Share API if available

Always mock in tests.

// In tests
vi.mock('@capacitor/filesystem', () => ({
  Filesystem: {
    writeFile: vi.fn().mockResolvedValue({ uri: 'file://' }),
    readFile: vi.fn().mockResolvedValue({ data: '...' }),
  },
}));

Distribution Between Devices

  • Export on device A (tablet at market or home)
  • Transfer via USB/OTG to device B
  • Import on device B
  • All offline, no network needed
  • Works with any file manager

Best Practices

  • Always version exports
  • Validate before importing
  • Provide clear error messages
  • Don't silently corrupt data
  • Test migrations with real export files
  • Keep backward compatibility when possible
  • Log migration steps for debugging
  • Consider backing up before destructive import

Error Messages

Be user-friendly in Spanish (app is for CESTA in Colombia):

  • "Formato de archivo inválido"
  • "Versión de esquema incompatible. Actualice la aplicación."
  • "Error al leer el archivo"
  • "Datos importados correctamente"

Resources

  • See openspec/changes/add-toldo-poc-capacitor/specs/toldo-poc/spec.md for scenarios
  • JSON versioned format is critical for long-term maintainability
  • Test import/export round-trip