Files
memind/health-page-data-document-store.mjs
T
john 2baf29b3ae feat(health): complete P0 health channel — baseline engine, page-data, MindSpace UI
Deliver encrypted health zone, observation API, baseline maturity pipeline,
page-data bindings, and H5/WeChat channel integration for health P0.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-09 18:04:57 +08:00

90 lines
3.0 KiB
JavaScript

import { createUserDataSpaceService } from './user-data-space-service.mjs';
import { ensureHealthPageDataForUser } from './health-page-data-bootstrap.mjs';
import { HEALTH_DOCUMENTS_DATASET } from './health-page-data-schema.mjs';
import { mapPgDocumentRow } from './health-page-data-map.mjs';
const DATASET_NAME = HEALTH_DOCUMENTS_DATASET.name;
export function createPageDataHealthDocumentStore({
resolveWorkspaceRoot,
logger = console,
} = {}) {
if (typeof resolveWorkspaceRoot !== 'function') {
throw new Error('createPageDataHealthDocumentStore requires resolveWorkspaceRoot');
}
async function getUserDataSpace(userId) {
const workspaceRoot = await resolveWorkspaceRoot(userId);
if (!workspaceRoot) return null;
const service = createUserDataSpaceService({ workspaceRoot, userId: String(userId) });
await ensureHealthPageDataForUser(service, userId);
return service;
}
async function list(userId, { limit = 50 } = {}) {
const service = await getUserDataSpace(userId);
if (!service) return [];
try {
const result = await service.readDatasetRows(DATASET_NAME, {
limit: Math.min(Math.max(limit, 1), 200),
orderBy: 'created_at',
orderDir: 'desc',
});
return (result.rows ?? []).map((row) => mapPgDocumentRow(row, userId));
} catch (error) {
if (error?.code === 'dataset_not_found') return [];
throw error;
}
}
async function insert(userId, document) {
if (document?.confirmed !== true) {
const error = Object.assign(new Error('报告必须确认归档后才能保存'), {
code: 'health_document_unconfirmed',
});
throw error;
}
const service = await getUserDataSpace(userId);
if (!service) {
const error = Object.assign(new Error('用户健康数据空间不可用'), { code: 'health_storage_unavailable' });
throw error;
}
const title = document.notes?.trim() || document.title?.trim() || '健康报告归档';
const extractedMetrics = document.extractedMetrics ?? [];
try {
const { row } = await service.insertDatasetRow(DATASET_NAME, {
doc_type: document.docType ?? 'other',
report_date: document.reportDate ?? null,
institution: document.institution ?? null,
title,
asset_id: document.assetId ?? null,
ocr_text: document.ocrText ?? null,
extracted_metrics: Array.isArray(extractedMetrics)
? JSON.stringify(extractedMetrics)
: extractedMetrics,
extraction_status: document.extractionStatus ?? 'pending',
});
const mapped = mapPgDocumentRow(row, userId);
return {
...mapped,
imageUrl: document.imageUrl ?? null,
notes: document.notes ?? null,
source: document.source ?? 'manual',
ocrText: document.ocrText ?? null,
extractedMetrics,
};
} catch (error) {
logger.warn?.('Page Data health document insert failed:', error);
throw error;
}
}
return {
backend: 'page_data',
list,
insert,
};
}