/** * InMemoryQboClient — deterministic in-memory QboClientInterface for dev. * * Holds a few FAKE QBO vendor records in memory. Each carries a fabricated * taxId so the redaction egress path has a sensitive target to mask before a * response leaves the server. Filters by case-insensitive substring on * displayName and respects maxResults. No OAuth, no network. * * This is for build-plan §4 "in-memory dev clients (tools return real data * locally)". */ import type { QboClientInterface, QboVendor, SearchVendorsParams, SearchVendorsResult, } from './client.js'; const SEED_VENDORS: QboVendor[] = [ { id: '101', displayName: 'Harbor Electric Co.', email: 'ap@harborelectric.example', phone: '(631) 555-0142', active: true, balance: 0, taxId: '12-3456789', }, { id: '102', displayName: 'Coastal Supply & Hardware', email: 'billing@coastalsupply.example', phone: '(631) 555-0188', active: true, balance: 1842.5, taxId: '98-7654321', }, { id: '103', displayName: 'Tidewater Plumbing LLC', phone: '(631) 555-0123', active: false, balance: 0, taxId: '45-6789012', }, ]; /** In-memory QboClientInterface seeded with fake vendors (taxId populated). */ export class InMemoryQboClient implements QboClientInterface { async searchVendors(params: SearchVendorsParams): Promise { const needle = params.query.trim().toLowerCase(); const matched = needle.length === 0 ? SEED_VENDORS : SEED_VENDORS.filter((v) => v.displayName.toLowerCase().includes(needle)); const limit = params.maxResults ?? 20; return { vendors: matched.slice(0, limit), totalCount: matched.length, }; } }