← back to Fm Wallpaper Sync

sync.mjs

56 lines

#!/usr/bin/env node
// Nightly: pull ALL live FileMaker WALLPAPER records → /tmp/fm_wallpaper_full.csv
// Reuses the filemaker-mcp Claris-ID client. Read-only against FileMaker.
// Creds are read live from ~/.claude.json (no secret duplication).
import fs from 'fs';
import os from 'os';
import path from 'path';

const cfg = JSON.parse(fs.readFileSync(path.join(os.homedir(), '.claude.json'), 'utf8'));
const env = cfg.mcpServers?.filemaker?.env || {};
for (const [k, v] of Object.entries(env)) if (v != null) process.env[k] = String(v);

const fm = await import('/Users/macstudio3/Projects/filemaker-mcp/src/fm-client.js');

const DB = 'WALLPAPER', LAYOUT = 'Basic List of Fields', PAGE = 1000;
const OUT = process.argv[2] || '/tmp/fm_wallpaper_full.csv';

// FM field name -> CSV column
const F = [
  ['combo sku','combo_sku'], ['Series','series'], ['JS Pattern','js_pattern'],
  ['Mfr Pattern','mfr_pattern'], ['Supplier','supplier'], ['JPG Name','jpg_name'],
  ['Width','width'], ['Border','border'], ['Repeat','repeat'], ['Five Ten Code','five_ten'],
  ['Account #','account'], ['Line','line'], ['Minimum','minimum'],
  ['Date Line Put Up:','date_line'], ['Page','page'],
  ['Retail Price','retail'], ['Cost','cost'], ['Net Price','net'],
];
const HEADER = [...F.map(x => x[1]), 'record_id'];
const q = s => '"' + String(s ?? '').replace(/"/g, '""') + '"';

const out = fs.createWriteStream(OUT);
out.write(HEADER.join(',') + '\n');

let offset = 1, total = null, pages = 0, written = 0;
const t0 = Date.now();
while (true) {
  let res, tries = 0;
  while (true) {
    try { res = await fm.listRecords(DB, LAYOUT, { limit: PAGE, offset }); break; }
    catch (e) { if (++tries >= 4) throw e; await new Promise(r => setTimeout(r, 1500 * tries)); }
  }
  total = res?.dataInfo?.totalRecordCount ?? total;
  const recs = res?.records || [];
  if (!recs.length) break;
  for (const r of recs) {
    const fd = r.fieldData || {};
    const row = F.map(([fmName]) => q(fd[fmName])).concat(q(r.recordId));
    out.write(row.join(',') + '\n');
    written++;
  }
  pages++; offset += PAGE;
  if (pages % 25 === 0) console.error(`  page ${pages} offset ${offset - 1}/${total} written=${written} ${((Date.now()-t0)/1000|0)}s`);
  if (total && offset > total) break;
}
await new Promise(r => out.end(r));
console.error(`PULL DONE pages=${pages} total=${total} written=${written} -> ${OUT} (${((Date.now()-t0)/1000|0)}s)`);