T24: Add try/catch to export functions, use shared types, return ExportResult

This commit is contained in:
2026-06-22 23:49:18 +00:00
parent 4f0d750741
commit 056e552ef4
+65 -72
View File
@@ -1,64 +1,14 @@
import type { YjsDocument } from '../crdt/YjsDocument';
import type {
CADLayer,
CADProperties,
CADElement,
ExportData,
ExportOptions,
ExportResult,
} from '../types/cad.types';
// ── Types ───────────────────────────────────────────────────────────────────
interface CADLayer {
id: string;
name: string;
visible: boolean;
locked: boolean;
color?: string;
lineType?: string;
transparency?: number;
sortOrder?: number;
}
interface CADProperties {
fill?: string;
stroke?: string;
strokeWidth?: number;
rotation?: number;
lineType?: 'solid' | 'dashed' | 'dotted';
radius?: number;
x1?: number;
y1?: number;
x2?: number;
y2?: number;
points?: Array<{ x: number; y: number }>;
text?: string;
fontSize?: number;
startAngle?: number;
endAngle?: number;
[key: string]: unknown;
}
interface CADElement {
id: string;
type: string;
layerId: string;
x: number;
y: number;
width: number;
height: number;
properties: CADProperties;
}
interface ExportData {
version: string;
exportedAt: number;
projectMeta: Record<string, unknown>;
layers: CADLayer[];
elements: CADElement[];
}
interface ExportOptions {
includeHiddenLayers?: boolean;
includeInvisibleElements?: boolean;
pageSize?: 'a4' | 'a3' | 'letter';
landscape?: boolean;
}
// ── Helpers ──────────────────────────────────────────────────────────────────
// ── Helpers ───────────────────────────────────────────────────────────────────
function hexToRgb(hex: string): { r: number; g: number; b: number } {
const clean = hex.replace('#', '');
@@ -150,22 +100,39 @@ function downloadBlob(content: string | Blob, filename: string, mimeType: string
URL.revokeObjectURL(url);
}
// ── JSON Export ──────────────────────────────────────────────────────────────
// ── JSON Export ──────────────────────────────────────────────────────────────
export function exportJSON(yjsDoc: YjsDocument, filename = 'cad-export.json'): void {
export function exportJSON(yjsDoc: YjsDocument, filename = 'cad-export.json'): ExportResult {
try {
const data = collectExportData(yjsDoc, {});
const json = JSON.stringify(data, null, 2);
downloadBlob(json, filename, 'application/json');
return { success: true, data: json };
} catch (e) {
return {
success: false,
error: `exportJSON failed: ${(e as Error).message}`,
};
}
}
export function exportJSONString(yjsDoc: YjsDocument): string {
export function exportJSONString(yjsDoc: YjsDocument): ExportResult {
try {
const data = collectExportData(yjsDoc, {});
return JSON.stringify(data, null, 2);
const json = JSON.stringify(data, null, 2);
return { success: true, data: json };
} catch (e) {
return {
success: false,
error: `exportJSONString failed: ${(e as Error).message}`,
};
}
}
// ── SVG Export ───────────────────────────────────────────────────────────────
// ── SVG Export ───────────────────────────────────────────────────────────────
export function exportSVG(yjsDoc: YjsDocument, filename = 'cad-export.svg', options: ExportOptions = {}): void {
export function exportSVG(yjsDoc: YjsDocument, filename = 'cad-export.svg', options: ExportOptions = {}): ExportResult {
try {
const data = collectExportData(yjsDoc, options);
let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
@@ -262,11 +229,19 @@ export function exportSVG(yjsDoc: YjsDocument, filename = 'cad-export.svg', opti
svgParts.push('</svg>');
const svg = svgParts.join('\n');
downloadBlob(svg, filename, 'image/svg+xml');
return { success: true, data: svg };
} catch (e) {
return {
success: false,
error: `exportSVG failed: ${(e as Error).message}`,
};
}
}
// ── DXF Export ───────────────────────────────────────────────────────────────
// ── DXF Export ───────────────────────────────────────────────────────────────
export function exportDXF(yjsDoc: YjsDocument, filename = 'cad-export.dxf', options: ExportOptions = {}): void {
export function exportDXF(yjsDoc: YjsDocument, filename = 'cad-export.dxf', options: ExportOptions = {}): ExportResult {
try {
const data = collectExportData(yjsDoc, options);
const lines: string[] = [];
@@ -424,15 +399,23 @@ export function exportDXF(yjsDoc: YjsDocument, filename = 'cad-export.dxf', opti
const dxf = lines.join('\n');
downloadBlob(dxf, filename, 'application/dxf');
return { success: true, data: dxf };
} catch (e) {
return {
success: false,
error: `exportDXF failed: ${(e as Error).message}`,
};
}
}
// ── PDF Export ───────────────────────────────────────────────────────────────
// ── PDF Export ───────────────────────────────────────────────────────────────
export async function exportPDF(
yjsDoc: YjsDocument,
filename = 'cad-export.pdf',
options: ExportOptions = {}
): Promise<void> {
): Promise<ExportResult> {
try {
const data = collectExportData(yjsDoc, options);
const { jsPDF } = await import('jspdf');
@@ -553,9 +536,16 @@ export async function exportPDF(
);
pdf.save(filename);
return { success: true };
} catch (e) {
return {
success: false,
error: `exportPDF failed: ${(e as Error).message}`,
};
}
}
// ── Unified Export ───────────────────────────────────────────────────────────
// ── Unified Export ─────────────────────────────────────────────────────────────
export type ExportFormat = 'json' | 'svg' | 'dxf' | 'pdf';
@@ -564,7 +554,7 @@ export async function exportDrawing(
format: ExportFormat,
filename?: string,
options?: ExportOptions
): Promise<void> {
): Promise<ExportResult> {
const ext = format;
const name = filename || `cad-export.${ext}`;
@@ -578,6 +568,9 @@ export async function exportDrawing(
case 'pdf':
return exportPDF(yjsDoc, name, options);
default:
throw new Error(`Unsupported export format: ${format}`);
return {
success: false,
error: `Unsupported export format: ${format}`,
};
}
}