vinmonopolet-ts
Version:
Extracts information on products, categories and stores from Vinmonopolet
145 lines (144 loc) • 7.12 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.fromDTOToPopulatedProduct = exports.fromDTOToBaseProduct = void 0;
const tryParseFloat_1 = require("../../util/tryParseFloat");
const Category_1 = __importDefault(require("../Category"));
const FoodPairing_1 = __importDefault(require("../FoodPairing"));
const ProductImage_1 = __importDefault(require("../ProductImage"));
const RawMaterial_1 = __importDefault(require("../RawMaterial"));
const Volume_1 = require("../Volume");
const BaseProduct_1 = __importDefault(require("./BaseProduct"));
const PopulatedProduct_1 = require("./PopulatedProduct");
function fromDTOToBaseProduct(dto) {
return new BaseProduct_1.default(dto.code, dto.name, dto.url, dto.price?.value ?? 0, calculatePricePerLiter(dto.price?.value, dto.volume), dto.images.map(mapToProductImage), mapToVolume(dto.volume), mapToCategory(dto.main_category), mapToCategory(dto.main_sub_category), mapToCategory(dto.main_country), mapToCategory(dto.district), mapToCategory(dto.sub_District), dto.product_selection, dto.productAvailability, dto.buyable, dto.status);
}
exports.fromDTOToBaseProduct = fromDTOToBaseProduct;
function fromDTOToPopulatedProduct(dto) {
return new PopulatedProduct_1.PopulatedProduct(dto.code, dto.name, dto.url, dto.price?.value ?? 0, calculatePricePerLiter(dto.price?.value, dto.volume), dto.images?.map(mapToProductImage) ?? [], mapToVolume(dto.volume), mapToCategory(dto.main_category), mapToCategory(dto.main_sub_category), mapToCategory(dto.main_country), mapToCategory(dto.district), mapToCategory(dto.sub_District), dto.product_selection, dto.buyable, dto.status, getAbvFromTraits(dto.content?.traits), dto.allergens, dto.bioDynamic, dto.color, dto.eco, dto.environmentalPackaging, dto.expired, dto.fairTrade, dto.gluten, dto.content?.isGoodFor?.map(mapToFoodPairing) ?? [], dto.kosher, dto.content?.storagePotential?.formattedValue, dto.packageType, dto.taste, dto.smell, dto.content?.ingredients?.map(mapToRawMaterial) ?? [], getSugarFromTraits(dto.content?.traits), getAcidFromTraits(dto.content?.traits), getPropertyFromCharacteristics(dto.content?.characteristics, "Garvestoffer"), getPropertyFromCharacteristics(dto.content?.characteristics, "Bitterhet"), getPropertyFromCharacteristics(dto.content?.characteristics, "Friskhet"), getPropertyFromCharacteristics(dto.content?.characteristics, "Fylde"), dto.ageLimit, dto.description, dto.summary, dto.method, mapToCategory(dto.main_producer), dto.distributor, dto.distributorId?.toString(), dto.wholeSaler, dto.year ? parseInt(dto.year) : undefined, parseStoreCategory(dto.storeCategory));
}
exports.fromDTOToPopulatedProduct = fromDTOToPopulatedProduct;
function parseStoreCategory(storeCategory) {
if (!storeCategory)
return [];
return storeCategory.split(",").map((s) => s.trim()).filter(Boolean);
}
function calculatePricePerLiter(price, volume) {
if (price === undefined ||
volume == undefined ||
Object.keys(volume).length === 0)
return 0;
const unit = getVolumeUnit(volume);
switch (unit) {
case "cl":
return price / (volume.value / 100);
case "dl":
return price / volume.value / 10;
case "l":
return price / volume.value;
default:
console.warn(`Unknown volume unit ${unit}. Unable to calculate price per liter`);
return 0;
}
}
function mapToCategory(input) {
if (!input || (!input.name && !input.code && !input.url)) {
return undefined;
}
return new Category_1.default(input);
}
function getVolumeUnit(input) {
const split = input.formattedValue.split(" ");
if (split.length != 2) {
console.warn(`Unable to find volume unit from string ${input.formattedValue}`);
return "";
}
return split[1].trim().toLowerCase();
}
function mapToVolume(input) {
if (input === undefined || Object.keys(input).length === 0)
return undefined;
return new Volume_1.Volume(input.value, input.formattedValue, getVolumeUnit(input));
}
function mapToProductImage(input) {
return new ProductImage_1.default({
format: input.format,
altText: input.altText,
imageType: input.imageType,
url: input.url,
});
}
function getAbvFromTraits(traits) {
if (!traits)
return 0;
const alcoholTrait = traits.find((trait) => trait.name === "Alkohol");
if (!alcoholTrait) {
console.warn("Unable to get abv from response. No trait with 'Alcohol'");
return 0;
}
const split = alcoholTrait.formattedValue.split("%");
if (split.length != 2) {
console.warn("Unable to get abv from alcohol formatted value: " +
alcoholTrait.formattedValue);
return 0;
}
return parseFloat(split[0]);
}
function mapToFoodPairing(isGoodFor) {
return FoodPairing_1.default[isGoodFor.code];
}
function mapToRawMaterial(ingredients) {
return new RawMaterial_1.default({
id: ingredients.code,
name: ingredients.readableValue,
percentage: 100,
});
}
function getSugarFromTraits(traits) {
if (!traits)
return undefined;
const trait = traits.find((x) => x.name.toLowerCase() === "sukker");
if (!trait)
return undefined;
const formattedValue = trait.formattedValue;
// If the value starts with "Under", preserve the full string
if (formattedValue.toLowerCase().startsWith("under 3 g/l")) {
return 0;
}
const split = formattedValue.split(" ");
return (0, tryParseFloat_1.tryParseFloat)(split[0]) ?? (0, tryParseFloat_1.tryParseFloat)(split[1]);
}
function getAcidFromTraits(traits) {
if (!traits)
return undefined;
const trait = traits.find((x) => x.name.toLowerCase() === "syre");
if (!trait)
return undefined;
try {
const split = trait.formattedValue.split(" ");
return (0, tryParseFloat_1.tryParseFloat)(split[0]) ?? (0, tryParseFloat_1.tryParseFloat)(split[1]);
}
catch (e) {
return undefined;
}
}
function getPropertyFromCharacteristics(characteristics, property) {
if (!characteristics)
return undefined;
const characteristic = characteristics.find((x) => x.name.toLowerCase() === property.toLowerCase());
if (characteristic === undefined)
return undefined;
try {
const split = characteristic.readableValue.split(",");
const [currentValuesString, maxValueString] = split[1].trim().split("av");
const currentValue = parseInt(currentValuesString.trim());
const maxValue = parseInt(maxValueString.trim());
return Math.round((currentValue / maxValue) * 100);
}
catch (e) {
console.warn(`Error parsing characteristic ${property}:`, e);
return undefined;
}
}