UNPKG

ikea-availability-checker

Version:

ikea product in-store availability checker and product search

154 lines (153 loc) 7.46 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.IngkaApi = exports.BASE_URL_DEFAULT = exports.PRODUCT_AVAILABILITY = void 0; const axios_1 = __importStar(require("axios")); const stores_1 = require("./stores"); const ingkaErrors_1 = require("./ingkaErrors"); // clientids taken from IKEA.tld websites they may change in the future const CLIENT_ID_US = "da465052-7912-43b2-82fa-9dc39cdccef8"; var PRODUCT_AVAILABILITY; (function (PRODUCT_AVAILABILITY) { PRODUCT_AVAILABILITY["HIGH_IN_STOCK"] = "HIGH_IN_STOCK"; PRODUCT_AVAILABILITY["LOW_IN_STOCK"] = "LOW_IN_STOCK"; PRODUCT_AVAILABILITY["OUT_OF_STOCK"] = "OUT_OF_STOCK"; })(PRODUCT_AVAILABILITY || (exports.PRODUCT_AVAILABILITY = PRODUCT_AVAILABILITY = {})); exports.BASE_URL_DEFAULT = "https://api.ingka.ikea.com"; class IngkaApi { constructor(clientId = CLIENT_ID_US, options = {}) { this.cache = new Map(); this.client = axios_1.default.create({ timeout: 5000, baseURL: exports.BASE_URL_DEFAULT, headers: { "x-client-id": clientId || CLIENT_ID_US, accept: "application/json;version=1", }, ...options, }); } parseAvailabilitiesResponse(responseData) { // the INGKA API response can contain items which don’t belong to a store // but to general storage units or unknown things. We should filter // here just for items that list availabilities for a specific store // indicated by the "classUnitType" "STO". const itemsWithStores = responseData.availabilities.filter((item) => { var _a; return ((_a = item.classUnitKey) === null || _a === void 0 ? void 0 : _a.classUnitType) === "STO"; }); // filter for Items that have a "availableStocks" property const rawStockInfoItems = itemsWithStores .filter((item) => item.buyingOption !== null) .filter((item) => (0, stores_1.findOneById)(item.classUnitKey.classUnitCode)); // remove all stores which are not known return rawStockInfoItems.map((item) => { var _a, _b, _c; const stockInfo = { buCode: item.classUnitKey.classUnitCode, productId: item.itemKey.itemNo, stock: 0, store: (0, stores_1.findOneById)(item.classUnitKey.classUnitCode), }; if (item.availableForCashCarry) { const availability = item.buyingOption.cashCarry.availability; stockInfo.stock = parseInt(String(availability === null || availability === void 0 ? void 0 : availability.quantity), 10); stockInfo.createdAt = new Date((_a = availability === null || availability === void 0 ? void 0 : availability.updateDateTime) !== null && _a !== void 0 ? _a : ""); stockInfo.probability = availability === null || availability === void 0 ? void 0 : availability.probability.thisDay.messageType; } if ((_b = item.buyingOption.cashCarry.availability) === null || _b === void 0 ? void 0 : _b.restocks) { stockInfo.restockDate = new Date((_c = item.buyingOption.cashCarry.availability) === null || _c === void 0 ? void 0 : _c.restocks[0].earliestDate); } return stockInfo; }); } async getStoreProductAvailability(countryCode, productId, buCode) { var _a; const key = countryCode + productId; if (!this.cache.has(key)) { this.cache.set(key, this.getAvailabilities(countryCode, [productId])); } return (_a = this.cache.get(key)) === null || _a === void 0 ? void 0 : _a.then(arr => arr.find(item => { var _a; return ((_a = item.store) === null || _a === void 0 ? void 0 : _a.buCode) === buCode; })); } handleResponseError(response) { var _a, _b, _c; if (!((_a = response.data.errors) === null || _a === void 0 ? void 0 : _a.length)) return; const message = ((_c = (((_b = response.data) === null || _b === void 0 ? void 0 : _b.errors) || [])[0]) === null || _c === void 0 ? void 0 : _c.message) || 'Unknown response error'; throw new ingkaErrors_1.IngkaResponseError(message, response); } validateResponseStructure(data) { if (!data || !data.availabilities || !Array.isArray(data.availabilities) || !data.availabilities.every((obj) => typeof obj === "object")) { throw new ingkaErrors_1.IngkaParseError(`Unexpected response data structure detected`, data); } return true; } buildAvailabilityUri(countryCode, unitType = 'ru') { return `cia/availabilities/${unitType}/${countryCode}`; } async getAvailabilities( /** a single supported country code */ countryCode, /** one or multiple ikea article ids */ itemNos, /** value of expand parameter */ expand = ["StoresList", "Restocks"], /** optional additional request configuration settings */ options = {}) { const uri = this.buildAvailabilityUri(countryCode); options = options || {}; options.params = { // StoresList,Restocks,SalesLocations expand: (expand || ["StoresList", "Restocks"]).join(","), itemNos: (Array.isArray(itemNos) ? itemNos : [itemNos]).join(","), ...(options.params || {}), }; return this.client.get(uri, options) .then(response => { this.handleResponseError(response); this.validateResponseStructure(response.data); return this.parseAvailabilitiesResponse(response.data); }) .catch((err) => { var _a; if ((0, axios_1.isAxiosError)(err)) { const message = ((_a = err.response) === null || _a === void 0 ? void 0 : _a.data.message) || 'Unknown Response error'; throw new ingkaErrors_1.IngkaHttpError(message, err); } throw err; }); } } exports.IngkaApi = IngkaApi;