161 lines
4.5 KiB
Markdown
161 lines
4.5 KiB
Markdown
# Agent Skill: toldo-offline-export-import
|
|
|
|
## Metadata
|
|
```yaml
|
|
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)
|
|
|
|
```typescript
|
|
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
|
|
|
|
```typescript
|
|
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
|
|
|
|
```typescript
|
|
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.
|
|
|
|
```typescript
|
|
// 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
|