T24: Add try/catch to export functions, use shared types, return ExportResult
This commit is contained in:
@@ -1,64 +1,14 @@
|
|||||||
import type { YjsDocument } from '../crdt/YjsDocument';
|
import type { YjsDocument } from '../crdt/YjsDocument';
|
||||||
|
import type {
|
||||||
|
CADLayer,
|
||||||
|
CADProperties,
|
||||||
|
CADElement,
|
||||||
|
ExportData,
|
||||||
|
ExportOptions,
|
||||||
|
ExportResult,
|
||||||
|
} from '../types/cad.types';
|
||||||
|
|
||||||
// ── Types ────────────────────────────────────────────────────────────────────
|
// ── Helpers ───────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
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 ──────────────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
function hexToRgb(hex: string): { r: number; g: number; b: number } {
|
function hexToRgb(hex: string): { r: number; g: number; b: number } {
|
||||||
const clean = hex.replace('#', '');
|
const clean = hex.replace('#', '');
|
||||||
@@ -150,22 +100,39 @@ function downloadBlob(content: string | Blob, filename: string, mimeType: string
|
|||||||
URL.revokeObjectURL(url);
|
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 data = collectExportData(yjsDoc, {});
|
||||||
const json = JSON.stringify(data, null, 2);
|
const json = JSON.stringify(data, null, 2);
|
||||||
downloadBlob(json, filename, 'application/json');
|
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, {});
|
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);
|
const data = collectExportData(yjsDoc, options);
|
||||||
|
|
||||||
let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
|
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>');
|
svgParts.push('</svg>');
|
||||||
const svg = svgParts.join('\n');
|
const svg = svgParts.join('\n');
|
||||||
downloadBlob(svg, filename, 'image/svg+xml');
|
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 data = collectExportData(yjsDoc, options);
|
||||||
const lines: string[] = [];
|
const lines: string[] = [];
|
||||||
|
|
||||||
@@ -424,15 +399,23 @@ export function exportDXF(yjsDoc: YjsDocument, filename = 'cad-export.dxf', opti
|
|||||||
|
|
||||||
const dxf = lines.join('\n');
|
const dxf = lines.join('\n');
|
||||||
downloadBlob(dxf, filename, 'application/dxf');
|
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(
|
export async function exportPDF(
|
||||||
yjsDoc: YjsDocument,
|
yjsDoc: YjsDocument,
|
||||||
filename = 'cad-export.pdf',
|
filename = 'cad-export.pdf',
|
||||||
options: ExportOptions = {}
|
options: ExportOptions = {}
|
||||||
): Promise<void> {
|
): Promise<ExportResult> {
|
||||||
|
try {
|
||||||
const data = collectExportData(yjsDoc, options);
|
const data = collectExportData(yjsDoc, options);
|
||||||
|
|
||||||
const { jsPDF } = await import('jspdf');
|
const { jsPDF } = await import('jspdf');
|
||||||
@@ -553,9 +536,16 @@ export async function exportPDF(
|
|||||||
);
|
);
|
||||||
|
|
||||||
pdf.save(filename);
|
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';
|
export type ExportFormat = 'json' | 'svg' | 'dxf' | 'pdf';
|
||||||
|
|
||||||
@@ -564,7 +554,7 @@ export async function exportDrawing(
|
|||||||
format: ExportFormat,
|
format: ExportFormat,
|
||||||
filename?: string,
|
filename?: string,
|
||||||
options?: ExportOptions
|
options?: ExportOptions
|
||||||
): Promise<void> {
|
): Promise<ExportResult> {
|
||||||
const ext = format;
|
const ext = format;
|
||||||
const name = filename || `cad-export.${ext}`;
|
const name = filename || `cad-export.${ext}`;
|
||||||
|
|
||||||
@@ -578,6 +568,9 @@ export async function exportDrawing(
|
|||||||
case 'pdf':
|
case 'pdf':
|
||||||
return exportPDF(yjsDoc, name, options);
|
return exportPDF(yjsDoc, name, options);
|
||||||
default:
|
default:
|
||||||
throw new Error(`Unsupported export format: ${format}`);
|
return {
|
||||||
|
success: false,
|
||||||
|
error: `Unsupported export format: ${format}`,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user