import type { WellSampleDropData } from '../types' interface DroppedSampleTransfer { getData(format: string): string } export function parseDroppedSampleTransfer(transfer: DroppedSampleTransfer): WellSampleDropData | null { if (jsonPayload(transfer)) return parseDroppedSampleJson(transfer) return createTextDroppedSample(transfer.getData('text/plain')) } /** JSON payloads only — no `text/plain` fallback, so stray text drags are rejected. */ export function parseDroppedSampleJson(transfer: DroppedSampleTransfer): WellSampleDropData | null { const json = jsonPayload(transfer) if (!json) return null try { return normalizeDroppedSample(JSON.parse(json)) } catch { return null } } function jsonPayload(transfer: DroppedSampleTransfer): string { return transfer.getData('application/json') || transfer.getData('text/json') } export function createTextDroppedSample(text: string | null | undefined): WellSampleDropData | null { const sampleName = text?.trim() if (!sampleName) return null return { sampleName, label: sampleName, raw: sampleName, } } export function normalizeDroppedSample(raw: unknown): WellSampleDropData | null { if (!raw || typeof raw !== 'object') return null const record = raw as Record const sampleName = getString(record.sampleName) ?? getString(record.sample_name) ?? getString(record.name) ?? getString(record.label) const label = getString(record.label) ?? sampleName const sampleType = getString(record.sampleType) ?? getString(record.sample_type) ?? (record.type === 'sample' ? 'sample' : undefined) if (!sampleName && !label && !getString(record.id)) return null return { id: getString(record.id), sampleName, label, sampleType, injectionVolume: getPositive(record.injectionVolume ?? record.injection_volume), injectionCount: getPositive(record.injectionCount ?? record.injection_count), customMethod: getString(record.customMethod ?? record.custom_method) ?? null, metadata: getRecord(record.metadata), raw, } } function getString(value: unknown): string | undefined { return typeof value === 'string' && value.trim() ? value.trim() : undefined } /** Volumes and counts from an untrusted drag payload: zero or less is dropped. */ function getPositive(value: unknown): number | undefined { return typeof value === 'number' && Number.isFinite(value) && value > 0 ? value : undefined } function getRecord(value: unknown): Record | undefined { return value && typeof value === 'object' && !Array.isArray(value) ? value as Record : undefined }