import http from "node:http"; const port = Number(process.env.VENDOR_MOCK_PORT ?? 5142); let nextCompanyId = 103; let nextTechnicianId = 3; const companies = [ { companyId: 101, rowVersion: "rv-101-1", name: "Gateway Plumbing", companyPhone: "(314) 555-0100", email: "dispatch@gateway.test", address: "1 Market St", city: "St. Louis", state: "MO", zip: "63101", googleMapsUrl: "https://maps.google.com/gateway", notes: "Preferred after-hours vendor", technicians: [ { id: 1, contactName: "Adam Whyte", phone: "(314) 555-0198", email: "adam@gateway.test", preferredContact: "Email", tradeSpecialties: "Plumbing", isActive: true, totalJobs: 72, }, ], }, { companyId: 102, rowVersion: "rv-102-1", name: "Metro HVAC", companyPhone: "(314) 555-0110", email: "dispatch@metro.test", address: "2 Pine St", city: "Clayton", state: "MO", zip: "63105", googleMapsUrl: "", notes: "", technicians: [], }, ]; function json(response, body, status = 200) { response.writeHead(status, { "content-type": "application/json", "access-control-allow-origin": "*", }); response.end(JSON.stringify(body)); } async function readBody(request) { const chunks = []; for await (const chunk of request) chunks.push(chunk); return chunks.length ? JSON.parse(Buffer.concat(chunks).toString("utf8")) : {}; } function findCompany(url) { const vendorId = url.searchParams.get("vendorId"); const companyId = url.searchParams.get("companyId"); if (vendorId) { return companies.find((company) => company.technicians.some((technician) => String(technician.id) === vendorId), ); } return companies.find((company) => String(company.companyId) === companyId); } function companyFacet(company) { return { companyId: company.companyId, name: company.name, companyPhone: company.companyPhone, email: company.email, address: company.address, city: company.city, state: company.state, zip: company.zip, googleMapsUrl: company.googleMapsUrl, }; } function directoryRows() { return companies.flatMap((company) => company.technicians.length ? company.technicians.map((technician) => ({ Id: technician.id, CompanyId: company.companyId, CompanyName: company.name, ContactName: technician.contactName, Email: technician.email, Phone: technician.phone, CompanyPhone: company.companyPhone, City: company.city, State: company.state, TradeSpecialties: technician.tradeSpecialties, GoogleMapsUrl: company.googleMapsUrl, Notes: company.notes, TotalJobs: technician.totalJobs, IsActive: technician.isActive, PreferredContact: technician.preferredContact, })) : [ { Id: null, CompanyId: company.companyId, CompanyName: company.name, ContactName: "", Email: company.email, Phone: "", CompanyPhone: company.companyPhone, City: company.city, State: company.state, TradeSpecialties: "", GoogleMapsUrl: company.googleMapsUrl, Notes: company.notes, TotalJobs: 0, IsActive: true, PreferredContact: "Phone", }, ], ); } const server = http.createServer(async (request, response) => { const url = new URL(request.url ?? "/", `http://${request.headers.host}`); if (request.method === "OPTIONS") return json(response, {}); if (url.pathname === "/api/Vendor/GetVendorList") { const search = (url.searchParams.get("search") ?? "").toLowerCase(); const active = url.searchParams.get("isActive") !== "false"; const rows = directoryRows().filter( (row) => row.IsActive === active && (!search || `${row.CompanyName} ${row.ContactName} ${row.TradeSpecialties} ${row.City} ${row.State}` .toLowerCase() .includes(search)), ); return json(response, { Data: rows, TotalCount: rows.length, PageNumber: 1, PageSize: 12 }); } if (url.pathname === "/api/Vendor/facets") { return json(response, { data: { companies: companies.map(companyFacet), trades: ["Plumbing", "HVAC"], locations: companies.map((company) => ({ city: company.city, state: company.state, label: `${company.city}, ${company.state}`, })), jobBuckets: [], }, }); } if (url.pathname === "/api/vendor-company-roster" && request.method === "GET") { const company = findCompany(url); return company ? json(response, company) : json(response, { message: "Not found" }, 404); } if (url.pathname === "/api/vendor-company-roster" && request.method === "POST") { const body = await readBody(request); const company = { ...body, companyId: nextCompanyId++, rowVersion: `rv-${Date.now()}`, technicians: (body.technicians ?? []).map((technician) => ({ ...technician, id: nextTechnicianId++, totalJobs: 0, })), }; companies.push(company); return json(response, company); } const rosterMatch = url.pathname.match(/^\/api\/vendor-company-roster\/(\d+)$/); if (rosterMatch && request.method === "PUT") { const company = companies.find((item) => item.companyId === Number(rosterMatch[1])); if (!company) return json(response, { message: "Not found" }, 404); const body = await readBody(request); Object.assign(company, body, { companyId: company.companyId, rowVersion: `rv-${Date.now()}`, technicians: (body.technicians ?? []).map((technician) => ({ ...technician, id: technician.id ?? nextTechnicianId++, totalJobs: company.technicians.find((existing) => existing.id === technician.id)?.totalJobs ?? 0, })), }); return json(response, company); } const portalMatch = url.pathname.match(/^\/api\/vendors\/(\d+)\/portal-token$/); if (portalMatch) { return json(response, { data: { portalUrl: "https://vendor.example.test/token", issuedAt: new Date().toISOString(), expiresAt: new Date(Date.now() + 86_400_000).toISOString(), }, }); } const impactMatch = url.pathname.match(/^\/api\/vendors\/(\d+)\/deactivation-impact$/); if (impactMatch) { return json(response, { data: { vendorId: Number(impactMatch[1]), canDeactivate: true, openWorkOrders: [] }, }); } return json(response, { message: `No mock for ${request.method} ${url.pathname}` }, 404); }); server.listen(port, "127.0.0.1", () => { process.stdout.write(`Vendor E2E mock listening on http://127.0.0.1:${port}\n`); });