#!/usr/bin/env node /** * PO from photo (OCR) — CLI wrapper. * * node scripts/po-photo-ingest.mjs * * Delegates to the shared ingestPhotoAndCreate() helper in * `src/lib/api/photoIngest.ts`. Real OCR providers (OpenAI Vision / * Google Document AI / AWS Textract) live in that module; the CLI just * wires input + auth + output. * * Required env: * POCKETBASE_URL defaults to https://pb.jeistk.apphub.co.za * POCKETBASE_ADMIN_EMAIL defaults to david@wfsales.co.za * POCKETBASE_ADMIN_PASSWORD defaults to 1234567890 * OCR_PROVIDER openai | google | textract | stub (default stub) * OPENAI_API_KEY required for openai */ import fs from 'node:fs/promises'; import path from 'node:path'; import { fileURLToPath, pathToFileURL } from 'node:url'; import PocketBase from 'pocketbase'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); const ROOT = path.resolve(__dirname, '..'); const PB_URL = process.env.POCKETBASE_URL || 'https://pb.jeistk.apphub.co.za'; const PB_EMAIL = process.env.POCKETBASE_ADMIN_EMAIL || 'david@wfsales.co.za'; const PB_PASSWORD = process.env.POCKETBASE_ADMIN_PASSWORD || '1234567890'; async function main() { const input = process.argv[2]; if (!input) { console.error('Usage: node scripts/po-photo-ingest.mjs '); process.exit(2); } let image: Buffer; try { image = await fs.readFile(input); } catch { image = Buffer.from(input.replace(/^data:[^;]+;base64,/, ''), 'base64'); } const pb = new PocketBase(PB_URL); // Never let the SDK auto-cancel a request: parallel stock-item lookups in // photoIngest share one method+path and would otherwise cancel each other. pb.autoCancellation(false); await pb.admins.authWithPassword(PB_EMAIL, PB_PASSWORD); const photoUrl = pathToFileURL(path.join(ROOT, 'src/lib/api/photoIngest.ts')).href; const photo = await import(photoUrl); const result = await photo.ingestPhotoAndCreate({ pb, image, mimeType: 'image/png' }); console.log(JSON.stringify({ ok: true, ...result }, null, 2)); } main().catch((err) => { console.error(err?.message || err); process.exit(1); });