feat: estructura base OpenSpec + Skills + arquitectura limpia Capacitor+Dextie
This commit is contained in:
38
packages/services/src/__tests__/ExportImportService.test.ts
Normal file
38
packages/services/src/__tests__/ExportImportService.test.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { ExportImportService, CURRENT_SCHEMA_VERSION } from '../export-import/ExportImportService';
|
||||
|
||||
describe('ExportImportService', () => {
|
||||
const service = new ExportImportService();
|
||||
|
||||
it('exporta con versionado', () => {
|
||||
const data = {
|
||||
productores: [], productos: [], movimientosInventario: [],
|
||||
ventas: [], ventaLineas: [], gastos: [], ajustes: [], cuadres: []
|
||||
};
|
||||
const exp = service.exportAll(data);
|
||||
expect(exp.schemaVersion).toBe(CURRENT_SCHEMA_VERSION);
|
||||
expect(exp.appVersion).toBe('0.0.1');
|
||||
expect(exp.exportedAt).toBeTruthy();
|
||||
expect(exp.data).toEqual(data);
|
||||
});
|
||||
|
||||
it('valida y rechaza formato inválido', () => {
|
||||
expect(() => service.import({})).toThrow('Formato de archivo inválido');
|
||||
});
|
||||
|
||||
it('rechaza esquema incompatible más nuevo', () => {
|
||||
const bad = {
|
||||
schemaVersion: 999,
|
||||
appVersion: '0.0.1',
|
||||
exportedAt: new Date().toISOString(),
|
||||
data: { productores: [], productos: [], movimientosInventario: [], ventas: [], ventaLineas: [], gastos: [], ajustes: [], cuadres: [] }
|
||||
};
|
||||
expect(() => service.import(bad)).toThrow('Versión de esquema incompatible');
|
||||
});
|
||||
|
||||
it('importa datos válidos v1', () => {
|
||||
const exp = service.exportAll({ productores: [], productos: [], movimientosInventario: [], ventas: [], ventaLineas: [], gastos: [], ajustes: [], cuadres: [] });
|
||||
const imp = service.import(exp);
|
||||
expect(imp.schemaVersion).toBe(CURRENT_SCHEMA_VERSION);
|
||||
});
|
||||
});
|
||||
56
packages/services/src/export-import/ExportImportService.ts
Normal file
56
packages/services/src/export-import/ExportImportService.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
import type { Productor, Producto, MovimientoInventario, Venta, VentaLinea, Gasto, Ajuste, CuadreCaja } from '@toldo/core';
|
||||
|
||||
export interface ExportData {
|
||||
schemaVersion: number;
|
||||
appVersion: string;
|
||||
exportedAt: string;
|
||||
data: {
|
||||
productores: Productor[];
|
||||
productos: Producto[];
|
||||
movimientosInventario: MovimientoInventario[];
|
||||
ventas: Venta[];
|
||||
ventaLineas: VentaLinea[];
|
||||
gastos: Gasto[];
|
||||
ajustes: Ajuste[];
|
||||
cuadres: CuadreCaja[];
|
||||
};
|
||||
}
|
||||
|
||||
export const CURRENT_SCHEMA_VERSION = 1;
|
||||
export const APP_VERSION = '0.0.1';
|
||||
|
||||
export class ExportImportService {
|
||||
exportAll(data: ExportData['data']): ExportData {
|
||||
return {
|
||||
schemaVersion: CURRENT_SCHEMA_VERSION,
|
||||
appVersion: APP_VERSION,
|
||||
exportedAt: new Date().toISOString(),
|
||||
data
|
||||
};
|
||||
}
|
||||
|
||||
validate(data: unknown): data is ExportData {
|
||||
if (!data || typeof data !== 'object') {
|
||||
throw new Error('Formato de archivo inválido');
|
||||
}
|
||||
const d = data as any;
|
||||
if (typeof d.schemaVersion !== 'number') throw new Error('Formato de archivo inválido');
|
||||
if (typeof d.appVersion !== 'string') throw new Error('Formato de archivo inválido');
|
||||
if (!d.exportedAt) throw new Error('Formato de archivo inválido');
|
||||
if (!d.data || typeof d.data !== 'object') throw new Error('Formato de archivo inválido');
|
||||
const required = ['productores', 'productos', 'movimientosInventario', 'ventas', 'ventaLineas', 'gastos', 'ajustes', 'cuadres'];
|
||||
for (const key of required) {
|
||||
if (!Array.isArray(d.data[key])) throw new Error('Formato de archivo inválido');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
import(data: unknown): ExportData {
|
||||
this.validate(data);
|
||||
if ((data as ExportData).schemaVersion > CURRENT_SCHEMA_VERSION) {
|
||||
throw new Error('Versión de esquema incompatible. Actualice la aplicación.');
|
||||
}
|
||||
// Simple pass-through for v1; migrations would go here
|
||||
return data as ExportData;
|
||||
}
|
||||
}
|
||||
1
packages/services/src/index.ts
Normal file
1
packages/services/src/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './export-import/ExportImportService';
|
||||
Reference in New Issue
Block a user