← back to Mfr Review Viewer Corruption
lib/fm-record-snapshot.mjs
59 lines
// fm-record-snapshot.mjs — READ-ONLY full-field snapshot of ONE WALLPAPER master.
//
// Given a FileMaker recordId, returns its COMPLETE fieldData from the WALLPAPER db
// via the filemaker-mcp getRecord (import-only; does NOT modify that project). Used
// two ways:
// • /api/fm-record-snapshot — the viewer shows the full record before proposing a delete.
// • /api/stage — the server writes each delete-candidate's full field snapshot to
// data/restore/<recordId>-<ISO>.json so an APPROVED delete is reversible (recreatable).
//
// PURELY READ-ONLY: FileMaker record GET only. Never writes to FileMaker. Loads the
// filemaker-mcp .env for FM Cloud creds. Same layout the candidates resolver uses.
import { readFileSync, existsSync } from 'node:fs';
import path from 'node:path';
import os from 'node:os';
const FM_PROJECT = path.join(os.homedir(), 'Projects', 'filemaker-mcp');
const FM_ENV = path.join(FM_PROJECT, '.env');
const FM_CLIENT = path.join(FM_PROJECT, 'src', 'fm-client.js');
const FM_DB = 'WALLPAPER';
const FM_LAYOUT = '*List Wallpapers - Full View';
// ---- load the filemaker-mcp .env (read-only) so FM Cloud creds are present ----
function loadFmEnv() {
if (!existsSync(FM_ENV)) return;
for (const line of readFileSync(FM_ENV, 'utf8').split('\n')) {
const m = line.match(/^([A-Z_]+)=(.*)$/);
if (m && !process.env[m[1]]) process.env[m[1]] = m[2];
}
}
loadFmEnv();
// lazy-import getRecord (ES module) once, cached
let _getRecord = null;
async function getGetRecord() {
if (_getRecord) return _getRecord;
const mod = await import('file://' + FM_CLIENT);
_getRecord = mod.getRecord;
return _getRecord;
}
// Return { recordId, db, layout, captured_at, fieldData, modId } for one master.
// Throws on FM/creds error (caller catches + degrades).
export async function snapshotRecord(recordId) {
const rid = String(recordId || '').trim();
if (!rid) throw new Error('recordId required');
const getRecord = await getGetRecord();
const rec = await getRecord(FM_DB, FM_LAYOUT, rid);
if (!rec) throw new Error(`WALLPAPER master ${rid} not found`);
return {
recordId: rec.recordId || rid,
db: FM_DB,
layout: FM_LAYOUT,
modId: rec.modId || null,
captured_at: new Date().toISOString(),
fieldData: rec.fieldData || {},
};
}