shoc-frontend-new/scripts/vendor-e2e-mock-server.mjs

225 lines
6.8 KiB
JavaScript
Raw Permalink Normal View History

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`);
});