/** * Migration — add `source_file` (text) to `price_list`. * * Stores the `raw_price_list.id` that an extracted line item came * from. Used by the n8n workflow's verification step: * * // After the POST loop * const actual = await pb.collection('price_list').getList(1, expected, { * filter: `source_file = "${rawId}"`, * }); * if (actual.items.length === expected) { * // safe to PATCH raw_price_list.status = "Completed" * } else { * // PATCH Failed with "X/Y items created" * } * * Also useful for the agent at quote time: "give me the full price * list for the file this row was sourced from." * * Idempotent: re-runs are safe. * * Run with: * npm run pb:migrate:price-list-source-file */ import PocketBase from "pocketbase"; const PB_URL = process.env.NEXT_PUBLIC_POCKETBASE_URL || "http://127.0.0.1:8090"; const ADMIN_EMAIL = process.env.PB_ADMIN_EMAIL; const ADMIN_PASSWORD = process.env.PB_ADMIN_PASSWORD; if (!ADMIN_EMAIL || !ADMIN_PASSWORD) { throw new Error("PB_ADMIN_EMAIL and PB_ADMIN_PASSWORD are required."); } async function main() { const pb = new PocketBase(PB_URL); await pb.collection("_superusers").authWithPassword(ADMIN_EMAIL, ADMIN_PASSWORD); const cols = await pb.collections.getFullList(); const priceList = cols.find((c) => c.name === "price_list"); if (!priceList) { throw new Error("price_list collection not found. Run the setup script first."); } if (priceList.fields.some((f) => f.name === "source_file")) { console.log("price_list.source_file already exists, skipping."); return; } await pb.collections.update(priceList.id, { fields: [ ...priceList.fields, { name: "source_file", type: "text", required: false, options: { max: 0 } }, ], }); console.log("Added price_list.source_file"); console.log("source_file migration complete."); } main().catch((err) => { console.error(err); process.exit(1); });