vinmonopolet-ts
Version:
Extracts information on products, categories and stores from Vinmonopolet
87 lines (86 loc) • 3.18 kB
JavaScript
import BaseStore from "../../models/store/BaseStore";
import Pagination from "../../models/Pagination";
import { GET } from "../../util/GET";
import { VINMONOPOLET_STORE_URL } from "../../constants";
const defaults = {
latitude: 59.9126054,
longitude: 10.7515334,
};
export function searchStores(opts) {
if (opts?.query) {
return searchByQuery(opts.query);
}
const lat = opts?.nearLocation?.lat ?? defaults.latitude;
const lon = opts?.nearLocation?.lon ?? defaults.longitude;
return searchByLocation(lat, lon, opts?.page, opts?.pageSize);
}
async function searchByQuery(querystring) {
const response = await GET(`${VINMONOPOLET_STORE_URL}autocomplete`, new URLSearchParams({ query: querystring }));
return { stores: response.stores.map(toBaseStore) };
}
async function searchByLocation(lat, lon, currentPage = 1, pageSize = 10) {
const query = {
fields: "BASIC",
currentPage: Math.max(0, currentPage - 1).toString(),
pageSize: pageSize.toString(),
latitude: lat.toString(),
longitude: lon.toString(),
};
const response = await GET(VINMONOPOLET_STORE_URL, new URLSearchParams(query));
return {
stores: response.stores.map(toBaseStore),
pagination: new Pagination(getPagination(query.currentPage, pageSize, response.pagination), { nearLocation: { lat, lon } }, searchStores),
};
}
function getPagination(currentPage, pageSize, res) {
return {
currentPage,
pageSize,
totalPages: res.totalPages,
totalResults: res.totalResults,
};
}
async function getAllStores() {
let allStores = [];
let currentPage = 0;
let numPages = 2;
while (currentPage < numPages) {
const { totalPages, stores } = await getPaginatedStores(currentPage);
currentPage += 1;
numPages = totalPages;
allStores = [...allStores, ...stores];
}
return allStores;
}
async function getPaginatedStores(page) {
const query = {
fields: "BASIC",
currentPage: page.toString(),
pageSize: "50",
};
const res = await GET(VINMONOPOLET_STORE_URL, new URLSearchParams(query));
const stores = await Promise.all(res.stores.map(toBaseStore));
return {
totalPages: res.pagination.totalPages,
stores,
};
}
function toBaseStore(store) {
const address = getZipAndCityFromFormattedString(store.address.formattedAddress);
return new BaseStore(store.id, store.displayName, store.address.line1, address?.zip, address?.city, store.geoPoint.latitude, store.geoPoint.longitude);
}
function getZipAndCityFromFormattedString(formattedAddressString) {
try {
const splitAddress = formattedAddressString.split(",");
const city = splitAddress[splitAddress.length - 1].trim();
const zip = splitAddress[splitAddress.length - 2].trim();
return {
zip,
city,
};
}
catch (error) {
console.warn("Unable to get zip and city from string: " + formattedAddressString);
}
}
export default getAllStores;