import type { MapRowOutcome, MapRowOutcomeStatus } from './durability-store'; export const MAP_ROW_OUTCOME_RUNTIME_FIELDS = { rowKey: '__deeplineRowKey', inputIndex: '__deeplineInputIndex', cellMetaPatch: '__deeplineCellMetaPatch', rowStatus: '__deeplineRowStatus', rowError: '__deeplineRowError', } as const; const MAP_ROW_OUTCOME_RUNTIME_FIELD_SET = new Set( Object.values(MAP_ROW_OUTCOME_RUNTIME_FIELDS), ); export type MapRowOutcomeRuntimeRow = Record; function isRecord(value: unknown): value is Record { return Boolean(value && typeof value === 'object' && !Array.isArray(value)); } export function resolveMapRowOutcomeKey( row: MapRowOutcomeRuntimeRow, ): string | null { const key = row[MAP_ROW_OUTCOME_RUNTIME_FIELDS.rowKey]; if (typeof key === 'string' && key.length > 0) return key; if (isRecord(row.data)) { const dataKey = row.data[MAP_ROW_OUTCOME_RUNTIME_FIELDS.rowKey]; if (typeof dataKey === 'string' && dataKey.length > 0) return dataKey; } return null; } export function mapRowOutcomeRuntimeFields(input: { key: string; inputIndex?: number | null; cellMetaPatch?: Record | null; status?: MapRowOutcomeStatus | null; error?: string | null; }): Record { return { [MAP_ROW_OUTCOME_RUNTIME_FIELDS.rowKey]: input.key, ...(typeof input.inputIndex === 'number' && Number.isFinite(input.inputIndex) ? { [MAP_ROW_OUTCOME_RUNTIME_FIELDS.inputIndex]: input.inputIndex } : {}), ...(input.cellMetaPatch ? { [MAP_ROW_OUTCOME_RUNTIME_FIELDS.cellMetaPatch]: input.cellMetaPatch } : {}), ...(input.status ? { [MAP_ROW_OUTCOME_RUNTIME_FIELDS.rowStatus]: input.status } : {}), ...(input.error !== undefined ? { [MAP_ROW_OUTCOME_RUNTIME_FIELDS.rowError]: input.error } : {}), }; } export function completedMapRowOutcome(input: { key: string; inputIndex?: number | null; data: Record; cellMetaPatch?: Record | null; }): MapRowOutcome { return { key: input.key, ...(input.inputIndex !== undefined ? { inputIndex: input.inputIndex } : {}), data: input.data, ...(input.cellMetaPatch ? { cellMetaPatch: input.cellMetaPatch } : {}), }; } export function failedMapRowOutcome(input: { key: string; inputIndex?: number | null; data: Record; cellMetaPatch?: Record | null; error?: string | null; }): MapRowOutcome { return { ...completedMapRowOutcome(input), status: 'failed', error: input.error ?? null, }; } export function mapRowOutcomeRuntimeRow( outcome: MapRowOutcome, ): Record { return { ...outcome.data, ...mapRowOutcomeRuntimeFields({ key: outcome.key, inputIndex: outcome.inputIndex, cellMetaPatch: outcome.cellMetaPatch, status: outcome.status, error: outcome.error, }), }; } export function copyMapRowOutcomeRuntimeFields< TTarget extends MapRowOutcomeRuntimeRow, >(target: TTarget, row: MapRowOutcomeRuntimeRow): TTarget { const writableTarget = target as MapRowOutcomeRuntimeRow; for (const runtimeField of MAP_ROW_OUTCOME_RUNTIME_FIELD_SET) { if (runtimeField in row) { writableTarget[runtimeField] = row[runtimeField]; } } return target; } export function stripMapRowOutcomeRuntimeFields< TRow extends MapRowOutcomeRuntimeRow, >(row: TRow): TRow { const data: MapRowOutcomeRuntimeRow = {}; for (const fieldName of Reflect.ownKeys(row)) { if ( typeof fieldName === 'string' && MAP_ROW_OUTCOME_RUNTIME_FIELD_SET.has(fieldName) ) { continue; } const descriptor = Object.getOwnPropertyDescriptor(row, fieldName); if (!descriptor) continue; Object.defineProperty(data, fieldName, descriptor); } return data as TRow; } export function mapRowOutcomeFromRuntimeRow( row: MapRowOutcomeRuntimeRow, ): MapRowOutcome | null { if (typeof row.key === 'string' && isRecord(row.data)) { const inputIndex = row.inputIndex; return { key: row.key, data: row.data, ...(typeof inputIndex === 'number' && Number.isFinite(inputIndex) ? { inputIndex } : {}), ...(isRecord(row.cellMetaPatch) ? { cellMetaPatch: row.cellMetaPatch } : {}), ...(row.status === 'failed' ? { status: 'failed', error: typeof row.error === 'string' ? row.error : null, } : {}), }; } const key = resolveMapRowOutcomeKey(row); if (!key) return null; const inputIndex = row[MAP_ROW_OUTCOME_RUNTIME_FIELDS.inputIndex]; const cellMetaPatch = row[MAP_ROW_OUTCOME_RUNTIME_FIELDS.cellMetaPatch]; const rowStatus = row[MAP_ROW_OUTCOME_RUNTIME_FIELDS.rowStatus]; const rowError = row[MAP_ROW_OUTCOME_RUNTIME_FIELDS.rowError]; return { key, ...(typeof inputIndex === 'number' && Number.isFinite(inputIndex) ? { inputIndex } : {}), data: stripMapRowOutcomeRuntimeFields(row), ...(isRecord(cellMetaPatch) ? { cellMetaPatch } : {}), ...(rowStatus === 'failed' ? { status: 'failed', error: typeof rowError === 'string' ? rowError : null, } : {}), }; } export function requireMapRowOutcomeFromRuntimeRow( row: MapRowOutcomeRuntimeRow, input: { tableNamespace: string }, ): MapRowOutcome { const outcome = mapRowOutcomeFromRuntimeRow(row); if (!outcome) { throw new Error( `persistCompletedMapRows received a row without a key for tableNamespace=${input.tableNamespace}.`, ); } return outcome; }