@stackend/api
Version:
JS bindings to api.stackend.com
1,224 lines (1,223 loc) • 61.5 kB
JavaScript
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.setIsShopifyApp = exports.setCustomerVatInfo = exports.setCommunityVATS = exports.setVATs = exports.getProductTypeLabel = exports.requestAddressFields = exports.requestCountries = exports.selectShipping = exports.clearCheckout = exports.requestCheckout = exports.checkoutSetEmail = exports.updateShippingAddress = exports.checkoutReplaceItems = exports.setItemQuantity = exports.removeItem = exports.addItem = exports.toLineItemArray = exports.getProductAndVariant2 = exports.getProductAndVariant = exports.checkoutUpdateOrCreateNew = exports.checkoutSetQuantity = exports.checkoutRemove = exports.checkoutAdd = exports.requestOrResetActiveCheckout = exports.createCheckout = exports.createCheckoutFromCart = exports.cartSetQuantity = exports.cartRemove = exports.cartAdd = exports.cartBuyerIdentityUpdate = exports.clearCart = exports.getCart = exports.createCart = exports.hasCheckoutErrors = exports.getProductListing = exports.getProductListingByKey = exports.clearCache = exports.getProductListKey = exports.requestCollections = exports.requestCollection = exports.requestMissingProducts = exports.requestMultipleProducts = exports.requestProduct = exports.requestProductsAndProductTypes = exports.requestProducts = exports.requestProductTypes = exports.getShopDefaults = exports.setShopDefaults = exports.CART_ID_LOCAL_STORAGE_NAME = exports.CHECKOUT_ID_LOCAL_STORAGE_NAME = void 0;
exports.setEnableCartNotifications = void 0;
var index_1 = require("./index");
var shopReducer_1 = require("./shopReducer");
var api_1 = require("../api");
var throbberActions_1 = require("../throbber/throbberActions");
var util_1 = require("../util");
var graphql_1 = require("../util/graphql");
var vat_1 = require("./vat");
exports.CHECKOUT_ID_LOCAL_STORAGE_NAME = 'checkout';
exports.CART_ID_LOCAL_STORAGE_NAME = 'cart';
/**
* Set shop default configuration
* @param defaults
*/
var setShopDefaults = function (defaults) {
return function (dispatch) {
dispatch({
type: shopReducer_1.SET_SHOP_DEFAULTS,
defaults: defaults
});
};
};
exports.setShopDefaults = setShopDefaults;
/**
* Get the shop default configuration
*/
var getShopDefaults = function () {
return function (dispatch, getState) {
return getState().shop.defaults;
};
};
exports.getShopDefaults = getShopDefaults;
/**
* Load product types into store
* @param req
*/
var requestProductTypes = function (req) {
return function (dispatch, _getState) { return __awaiter(void 0, void 0, void 0, function () {
var r;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!req.first) {
req.first = 250; /* 250 is max allowed */
}
return [4 /*yield*/, dispatch((0, index_1.listProductTypes)(req))];
case 1:
r = _a.sent();
if (!!r.error) return [3 /*break*/, 3];
return [4 /*yield*/, dispatch({ type: shopReducer_1.RECEIVE_PRODUCT_TYPES, json: r })];
case 2:
_a.sent();
_a.label = 3;
case 3: return [2 /*return*/, r];
}
});
}); };
};
exports.requestProductTypes = requestProductTypes;
/**
* Request a product listing
* @param req
*/
var requestProducts = function (req) {
return function (dispatch, getState) { return __awaiter(void 0, void 0, void 0, function () {
var r, key;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
(0, index_1.applyDefaults)(req, getState().shop.defaults);
return [4 /*yield*/, dispatch((0, index_1.listProducts)(req))];
case 1:
r = _a.sent();
if (!!r.error) return [3 /*break*/, 3];
key = dispatch((0, exports.getProductListKey)(req));
return [4 /*yield*/, dispatch({ type: shopReducer_1.RECEIVE_LISTING, json: r, request: req, key: key })];
case 2:
_a.sent();
_a.label = 3;
case 3: return [2 /*return*/, r];
}
});
}); };
};
exports.requestProducts = requestProducts;
/**
* Load products and product types into store
* @param req
*/
var requestProductsAndProductTypes = function (req) {
return function (dispatch, getState) { return __awaiter(void 0, void 0, void 0, function () {
var r, key;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
(0, index_1.applyDefaults)(req, getState().shop.defaults);
return [4 /*yield*/, dispatch((0, index_1.listProductsAndTypes)(req))];
case 1:
r = _a.sent();
if (!!r.error) return [3 /*break*/, 4];
key = dispatch((0, exports.getProductListKey)(req));
return [4 /*yield*/, dispatch({ type: shopReducer_1.RECEIVE_LISTING, json: r, request: req, key: key })];
case 2:
_a.sent();
return [4 /*yield*/, dispatch({ type: shopReducer_1.RECEIVE_PRODUCT_TYPES, json: r })];
case 3:
_a.sent();
_a.label = 4;
case 4: return [2 /*return*/, r];
}
});
}); };
};
exports.requestProductsAndProductTypes = requestProductsAndProductTypes;
/**
* Load a single product into store
* @param req
*/
var requestProduct = function (req) {
return function (dispatch, getState) { return __awaiter(void 0, void 0, void 0, function () {
var r;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!req.imageMaxWidth) {
req.imageMaxWidth = getState().shop.defaults.imageMaxWidth;
}
return [4 /*yield*/, dispatch((0, index_1.getProduct)(req))];
case 1:
r = _a.sent();
if (!!r.error) return [3 /*break*/, 3];
return [4 /*yield*/, dispatch({ type: shopReducer_1.RECEIVE_PRODUCT, json: r })];
case 2:
_a.sent();
_a.label = 3;
case 3: return [2 /*return*/, r];
}
});
}); };
};
exports.requestProduct = requestProduct;
/**
* Request multiple products
* @param req
*/
var requestMultipleProducts = function (req) {
return function (dispatch, getState) { return __awaiter(void 0, void 0, void 0, function () {
var r;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!req.imageMaxWidth) {
req.imageMaxWidth = getState().shop.defaults.imageMaxWidth;
}
return [4 /*yield*/, dispatch((0, index_1.getProducts)(req))];
case 1:
r = _a.sent();
if (!!r.error) return [3 /*break*/, 3];
return [4 /*yield*/, dispatch({ type: shopReducer_1.RECEIVE_MULTIPLE_PRODUCTS, json: r })];
case 2:
_a.sent();
_a.label = 3;
case 3: return [2 /*return*/, r];
}
});
}); };
};
exports.requestMultipleProducts = requestMultipleProducts;
/**
* Request missing products
* @param req
*/
var requestMissingProducts = function (req) {
return function (dispatch, getState) { return __awaiter(void 0, void 0, void 0, function () {
var shop, fetchHandles, _i, _a, h, p, r;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
shop = getState().shop;
if (!req.imageMaxWidth) {
req.imageMaxWidth = shop.defaults.imageMaxWidth;
}
fetchHandles = [];
for (_i = 0, _a = req.handles; _i < _a.length; _i++) {
h = _a[_i];
p = shop.products[h];
if (!p) {
fetchHandles.push(h);
}
}
if (fetchHandles.length == 0) {
return [2 /*return*/, (0, api_1.newXcapJsonResult)('success', { products: {} })];
}
return [4 /*yield*/, dispatch((0, index_1.getProducts)({ handles: fetchHandles, imageMaxWidth: req.imageMaxWidth }))];
case 1:
r = _b.sent();
if (!!r.error) return [3 /*break*/, 3];
return [4 /*yield*/, dispatch({ type: shopReducer_1.RECEIVE_MULTIPLE_PRODUCTS, json: r })];
case 2:
_b.sent();
_b.label = 3;
case 3: return [2 /*return*/, r];
}
});
}); };
};
exports.requestMissingProducts = requestMissingProducts;
/**
* Request a collection, if missing
* @param req
*/
var requestCollection = function (req) {
return function (dispatch, getState) { return __awaiter(void 0, void 0, void 0, function () {
var shop, collection, r;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
shop = getState().shop;
collection = shop.collections[req.handle];
if (collection) {
return [2 /*return*/, (0, api_1.newXcapJsonResult)('success', { collection: collection })];
}
if (!req.imageMaxWidth) {
req.imageMaxWidth = shop.defaults.listingImageMaxWidth;
}
return [4 /*yield*/, dispatch((0, index_1.getCollection)(req))];
case 1:
r = _a.sent();
if (!r.error) {
dispatch({
type: shopReducer_1.RECEIVE_COLLECTION,
request: req,
json: r
});
}
return [2 /*return*/, r];
}
});
}); };
};
exports.requestCollection = requestCollection;
/**
* Request a list of all collections, if missing
*/
var requestCollections = function () {
return function (dispatch, getState) { return __awaiter(void 0, void 0, void 0, function () {
var shop, r;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
shop = getState().shop;
if (shop.allCollections) {
return [2 /*return*/, (0, api_1.newXcapJsonResult)('success', {
collections: shop.allCollections
})];
}
return [4 /*yield*/, dispatch((0, index_1.getCollections)({}))];
case 1:
r = _a.sent();
if (!r.error) {
dispatch({
type: shopReducer_1.RECEIVE_COLLECTION_LIST,
collections: r.collections
});
}
return [2 /*return*/, r];
}
});
}); };
};
exports.requestCollections = requestCollections;
/**
* Get the key used to index the product listings in ShopState
* @param req
*/
var getProductListKey = function (req) {
return function (dispatch, getState) {
var defaults = getState().shop.defaults;
(0, index_1.applyDefaults)(req, defaults);
// NOTE: This must match the server side implementation
function append(s, values) {
if (values && values.length !== 0) {
var x = [];
for (var _i = 0, values_1 = values; _i < values_1.length; _i++) {
var v = values_1[_i];
x.push(v.toLowerCase());
}
x.sort(function (a, b) { return a.localeCompare(b); });
s += x.join(',');
}
s += ';';
return s;
}
var s = '';
s += (req.q || '') + ';';
s = append(s, req.productTypes);
s = append(s, req.tags);
s += (req.sort || index_1.ProductSortKeys.RELEVANCE) + ';';
s += req.imageMaxWidth + ';';
s += (req.first || '') + ';';
s += (req.after || '') + ';';
s += (req.last || '') + ';';
s += (req.before || '') + ';';
return s;
};
};
exports.getProductListKey = getProductListKey;
/**
* Clear store cache. Does not empty basket or product types
*/
var clearCache = function () {
return function (dispatch) { return __awaiter(void 0, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, dispatch({ type: shopReducer_1.SHOP_CLEAR_CACHE })];
case 1:
_a.sent();
return [2 /*return*/];
}
});
}); };
};
exports.clearCache = clearCache;
/**
* Get products from a listing
* @param key
*/
var getProductListingByKey = function (key) {
return function (dispatch, getState) {
if (key === null || typeof key === 'undefined') {
return null;
}
var shop = getState().shop;
var listing = shop.productListings[key];
return listing ? listing : null;
};
};
exports.getProductListingByKey = getProductListingByKey;
/**
* Get products from a listing
* @param req
*/
var getProductListing = function (req) {
return function (dispatch) {
var key = dispatch((0, exports.getProductListKey)(req));
return dispatch((0, exports.getProductListingByKey)(key));
};
};
exports.getProductListing = getProductListing;
/**
* Check if there are any kind of errors in the checkout
* @param result
*/
function hasCheckoutErrors(result) {
return (result &&
(typeof result.error !== 'undefined' || (result.checkoutUserErrors && result.checkoutUserErrors.length !== 0)));
}
exports.hasCheckoutErrors = hasCheckoutErrors;
/**
* Handle product data received via a cart:
* Adds the products to the store and transforms the returned data
* @param dispatch
* @param cart
*/
function handleCartProductData(dispatch, cart) {
if (!cart) {
return false;
}
var products = {};
var lines = { edges: [] };
(0, graphql_1.forEachGraphQLList)(cart.lines, function (i) {
var p = i.merchandise.product;
// Contains extra product data
if (typeof p['availableForSale'] === 'boolean') {
var product = p;
products[product.handle] = product;
// Remove the extra data
var li = {
node: __assign(__assign({}, i), { merchandise: {
id: i.merchandise.id,
product: {
id: i.merchandise.product.id,
handle: i.merchandise.product.handle
}
} })
};
lines.edges.push(li);
}
else {
lines.edges.push({ node: i });
}
});
cart.lines = lines;
if (Object.keys(products).length !== 0) {
dispatch({
type: shopReducer_1.RECEIVE_MULTIPLE_PRODUCTS,
json: (0, api_1.newXcapJsonResult)('success', {
products: products
})
});
}
dispatch({
type: shopReducer_1.RECEIVE_CART,
cart: cart
});
return true;
}
/**
* Create a cart
*/
function createCart(req) {
var _this = this;
return function (dispatch, getState) { return __awaiter(_this, void 0, void 0, function () {
var ci, communities, countryCode, r;
var _a, _b, _c, _d;
return __generator(this, function (_e) {
switch (_e.label) {
case 0:
_e.trys.push([0, , 3, 5]);
return [4 /*yield*/, dispatch((0, throbberActions_1.setModalThrobberVisible)(true))];
case 1:
_e.sent();
// FIXME: Improve country detection
if (!req.buyerIdentity) {
req.buyerIdentity = {};
}
if (!req.buyerIdentity.countryCode) {
ci = dispatch((0, vat_1.getCustomerInfo)());
if (ci && ci.customerCountryCode) {
req.buyerIdentity.countryCode = ci.customerCountryCode;
}
else {
communities = getState().communities;
countryCode = (_c = (_b = (_a = communities.community) === null || _a === void 0 ? void 0 : _a.settings) === null || _b === void 0 ? void 0 : _b.shop) === null || _c === void 0 ? void 0 : _c.countryCode;
if (countryCode) {
req.buyerIdentity.countryCode = countryCode;
}
}
}
return [4 /*yield*/, dispatch((0, index_1.createCart)(req))];
case 2:
r = _e.sent();
if (r.error || ((_d = r.userErrors) === null || _d === void 0 ? void 0 : _d.length) !== 0) {
return [2 /*return*/, r];
}
if (r.cart) {
dispatch((0, util_1.setLocalStorageItem)(exports.CART_ID_LOCAL_STORAGE_NAME, r.cart.id));
}
handleCartProductData(dispatch, r.cart);
return [2 /*return*/, r];
case 3: return [4 /*yield*/, dispatch((0, throbberActions_1.setModalThrobberVisible)(false))];
case 4:
_e.sent();
return [7 /*endfinally*/];
case 5: return [2 /*return*/];
}
});
}); };
}
exports.createCart = createCart;
/**
* If the user has established a cart, get it
* @param imageMaxWidth
* @param forceRefresh
*/
function getCart(_a) {
var _this = this;
var imageMaxWidth = _a.imageMaxWidth, forceRefresh = _a.forceRefresh;
return function (dispatch, getState) { return __awaiter(_this, void 0, void 0, function () {
var shop, useCache, cartId, r;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
shop = getState().shop;
useCache = typeof forceRefresh === 'undefined' || !forceRefresh;
if (useCache && shop.cart) {
return [2 /*return*/, shop.cart];
}
cartId = dispatch((0, util_1.getLocalStorageItem)(exports.CART_ID_LOCAL_STORAGE_NAME));
if (!cartId) {
return [2 /*return*/, null];
}
return [4 /*yield*/, dispatch((0, index_1.getCart)({ cartId: cartId, imageMaxWidth: imageMaxWidth }))];
case 1:
r = _a.sent();
if (r.cart) {
handleCartProductData(dispatch, r.cart);
return [2 /*return*/, r.cart];
}
return [4 /*yield*/, dispatch(clearCart())];
case 2:
_a.sent();
return [2 /*return*/, null];
}
});
}); };
}
exports.getCart = getCart;
/**
* Clear cart data and remove the id
*/
function clearCart() {
var _this = this;
return function (dispatch) { return __awaiter(_this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
dispatch((0, util_1.removeLocalStorageItem)(exports.CART_ID_LOCAL_STORAGE_NAME));
return [4 /*yield*/, dispatch({
type: shopReducer_1.CLEAR_CART
})];
case 1:
_a.sent();
return [2 /*return*/];
}
});
}); };
}
exports.clearCart = clearCart;
/**
* Alter buyer information
*/
function cartBuyerIdentityUpdate(buyerIdentity) {
var _this = this;
return function (dispatch) { return __awaiter(_this, void 0, void 0, function () {
var cart, r;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, , 4, 6]);
return [4 /*yield*/, dispatch((0, throbberActions_1.setModalThrobberVisible)(true))];
case 1:
_a.sent();
return [4 /*yield*/, dispatch(getCart({}))];
case 2:
cart = _a.sent();
if (!cart) {
// FIXME: Create empty cart here?
return [2 /*return*/, (0, api_1.newXcapJsonResult)('success', { cart: null })];
}
return [4 /*yield*/, dispatch((0, index_1.cartBuyerIdentityUpdate)({ cartId: cart.id, buyerIdentity: buyerIdentity }))];
case 3:
r = _a.sent();
if (r.cart) {
handleCartProductData(dispatch, r.cart);
}
return [2 /*return*/, r];
case 4: return [4 /*yield*/, dispatch((0, throbberActions_1.setModalThrobberVisible)(false))];
case 5:
_a.sent();
return [7 /*endfinally*/];
case 6: return [2 /*return*/];
}
});
}); };
}
exports.cartBuyerIdentityUpdate = cartBuyerIdentityUpdate;
/**
* Add an item to the cart or increment the quantity. Creating a new cart if needed.
* @param product
* @param variant
* @param quantity
*/
function cartAdd(product, variant, quantity) {
var _this = this;
return function (dispatch) { return __awaiter(_this, void 0, void 0, function () {
var q, lines, r, cart, line;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!product || !variant) {
throw new Error('product and variant required');
}
q = quantity || 1;
lines = [{ merchandiseId: variant.id, quantity: q }];
r = null;
_a.label = 1;
case 1:
_a.trys.push([1, , 11, 13]);
return [4 /*yield*/, dispatch((0, throbberActions_1.setModalThrobberVisible)(true))];
case 2:
_a.sent();
return [4 /*yield*/, dispatch(getCart({}))];
case 3:
cart = _a.sent();
if (!cart) return [3 /*break*/, 8];
line = (0, index_1.cartFindLine)(cart, variant.id);
if (!line) return [3 /*break*/, 5];
return [4 /*yield*/, dispatch(cartSetQuantity(variant.id, line.quantity + q))];
case 4:
r = _a.sent();
return [3 /*break*/, 7];
case 5: return [4 /*yield*/, dispatch((0, index_1.cartLinesAdd)({ cartId: cart.id, lines: lines }))];
case 6:
r = _a.sent();
if (!r.error) {
handleCartProductData(dispatch, r.cart);
}
_a.label = 7;
case 7: return [3 /*break*/, 10];
case 8: return [4 /*yield*/, dispatch(createCart({ lines: lines }))];
case 9:
r = _a.sent();
_a.label = 10;
case 10:
if (!r.error) {
dispatch({ type: shopReducer_1.ADD_TO_BASKET, product: product, variant: variant, variantId: variant.id, quantity: q });
}
return [2 /*return*/, r];
case 11: return [4 /*yield*/, dispatch((0, throbberActions_1.setModalThrobberVisible)(false))];
case 12:
_a.sent();
return [7 /*endfinally*/];
case 13: return [2 /*return*/];
}
});
}); };
}
exports.cartAdd = cartAdd;
/**
* For a product in the cart, decrement the quantity. Remove if 0.
* NOTE: This differs from the Shopify behavior that removes the line completely.
* @param product
* @param variant
* @param quantity
*/
function cartRemove(product, variant, quantity) {
var _this = this;
return function (dispatch, _getState) { return __awaiter(_this, void 0, void 0, function () {
var cart, line, r, q, newQuantity;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!product || !variant) {
throw new Error('product and variant required');
}
return [4 /*yield*/, dispatch(getCart({}))];
case 1:
cart = _a.sent();
if (!cart) {
// The cart has probably expired. Improve this situation?
return [2 /*return*/, (0, api_1.newXcapJsonResult)('success', { cart: null })];
}
line = (0, index_1.cartFindLine)(cart, variant.id);
if (line == null) {
console.warn('No such product variant in cart', variant.id, cart.lines.edges);
return [2 /*return*/, (0, api_1.newXcapJsonResult)('success', { cart: null })];
}
_a.label = 2;
case 2:
_a.trys.push([2, , 8, 10]);
return [4 /*yield*/, dispatch((0, throbberActions_1.setModalThrobberVisible)(true))];
case 3:
_a.sent();
r = null;
q = quantity || 1;
newQuantity = line.quantity - q;
if (!(newQuantity <= 0)) return [3 /*break*/, 5];
return [4 /*yield*/, dispatch((0, index_1.cartLinesRemove)({ cartId: cart.id, lineIds: [line.id] }))];
case 4:
r = _a.sent();
return [3 /*break*/, 7];
case 5: return [4 /*yield*/, dispatch((0, index_1.cartLinesUpdate)({
cartId: cart.id,
lines: [
{
id: line.id,
merchandiseId: line.merchandise.id,
quantity: newQuantity
}
]
}))];
case 6:
r = _a.sent();
_a.label = 7;
case 7:
if (!r.error) {
handleCartProductData(dispatch, r.cart);
dispatch({ type: shopReducer_1.REMOVE_FROM_BASKET, product: product, variant: variant, variantId: variant.id, quantity: q });
}
return [2 /*return*/, r];
case 8: return [4 /*yield*/, dispatch((0, throbberActions_1.setModalThrobberVisible)(false))];
case 9:
_a.sent();
return [7 /*endfinally*/];
case 10: return [2 /*return*/];
}
});
}); };
}
exports.cartRemove = cartRemove;
/**
* Set quantity of an item.
* @param variantId
* @param quantity
*/
function cartSetQuantity(variantId, quantity) {
var _this = this;
return function (dispatch) { return __awaiter(_this, void 0, void 0, function () {
var cart, line, r;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, dispatch(getCart({}))];
case 1:
cart = _a.sent();
if (!!cart) return [3 /*break*/, 3];
if (quantity < 1) {
return [2 /*return*/, (0, api_1.newXcapJsonResult)('success', { cart: null })];
}
return [4 /*yield*/, dispatch(createCart({ lines: [{ merchandiseId: variantId, quantity: quantity || 1 }] }))];
case 2: return [2 /*return*/, _a.sent()];
case 3:
line = (0, index_1.cartFindLine)(cart, variantId);
if (!line) {
console.warn('No such product variant in cart', variantId, cart.lines.edges);
return [2 /*return*/, (0, api_1.newXcapJsonResult)('success', { cart: null })];
}
_a.label = 4;
case 4:
_a.trys.push([4, , 10, 12]);
return [4 /*yield*/, dispatch((0, throbberActions_1.setModalThrobberVisible)(true))];
case 5:
_a.sent();
r = null;
if (!(quantity < 1)) return [3 /*break*/, 7];
return [4 /*yield*/, dispatch((0, index_1.cartLinesRemove)({ cartId: cart.id, lineIds: [line.id] }))];
case 6:
r = _a.sent();
return [3 /*break*/, 9];
case 7: return [4 /*yield*/, dispatch((0, index_1.cartLinesUpdate)({ cartId: cart.id, lines: [{ id: line.id, quantity: quantity, merchandiseId: variantId }] }))];
case 8:
r = _a.sent();
_a.label = 9;
case 9:
if (!r.error) {
handleCartProductData(dispatch, r.cart);
}
return [2 /*return*/, r];
case 10: return [4 /*yield*/, dispatch((0, throbberActions_1.setModalThrobberVisible)(false))];
case 11:
_a.sent();
return [7 /*endfinally*/];
case 12: return [2 /*return*/];
}
});
}); };
}
exports.cartSetQuantity = cartSetQuantity;
/**
* Create a checkout from the cart, possibly reusing
*/
function createCheckoutFromCart() {
var _this = this;
return function (dispatch, getState) { return __awaiter(_this, void 0, void 0, function () {
var cart, shop, lineItems;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, , 4, 5]);
dispatch((0, throbberActions_1.setModalThrobberVisible)(true));
return [4 /*yield*/, dispatch(getCart({}))];
case 1:
cart = _a.sent();
if (!cart) {
return [2 /*return*/, (0, api_1.newXcapJsonErrorResult)('cart_not_available')];
}
// Reuse existing checkout, if available. The customer may have entered address data
return [4 /*yield*/, dispatch((0, exports.requestOrResetActiveCheckout)({}))];
case 2:
// Reuse existing checkout, if available. The customer may have entered address data
_a.sent();
shop = getState().shop;
lineItems = (0, index_1.cartToLineItems)(cart);
return [4 /*yield*/, dispatch((0, exports.checkoutUpdateOrCreateNew)(shop, lineItems))];
case 3: return [2 /*return*/, _a.sent()];
case 4:
dispatch((0, throbberActions_1.setModalThrobberVisible)(false));
return [7 /*endfinally*/];
case 5: return [2 /*return*/];
}
});
}); };
}
exports.createCheckoutFromCart = createCheckoutFromCart;
/**
* Create a checkout
*/
function createCheckout(req) {
var _this = this;
return function (dispatch) { return __awaiter(_this, void 0, void 0, function () {
var r;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, , 5, 7]);
return [4 /*yield*/, dispatch((0, throbberActions_1.setModalThrobberVisible)(true))];
case 1:
_a.sent();
return [4 /*yield*/, dispatch((0, index_1.createCheckout)(req))];
case 2:
r = _a.sent();
if (!!hasCheckoutErrors(r)) return [3 /*break*/, 4];
if (r.response.checkout) {
dispatch((0, util_1.setLocalStorageItem)(exports.CHECKOUT_ID_LOCAL_STORAGE_NAME, r.response.checkout.id));
}
handleCheckoutProductData(dispatch, r.checkout);
return [4 /*yield*/, dispatch({
type: shopReducer_1.RECEIVE_CHECKOUT,
checkoutUserErrors: r.response.checkoutUserErrors,
checkout: r.response.checkout
})];
case 3:
_a.sent();
_a.label = 4;
case 4: return [2 /*return*/, r];
case 5: return [4 /*yield*/, dispatch((0, throbberActions_1.setModalThrobberVisible)(false))];
case 6:
_a.sent();
return [7 /*endfinally*/];
case 7: return [2 /*return*/];
}
});
}); };
}
exports.createCheckout = createCheckout;
/**
* If the user has an active checkout set in the local storage, request that checkout to be loaded.
* If the checkout is turned into an order, the checkout is reset in local storage.
* @param imageMaxWidth
*/
var requestOrResetActiveCheckout = function (_a) {
var imageMaxWidth = _a.imageMaxWidth;
return function (dispatch, getState) { return __awaiter(void 0, void 0, void 0, function () {
var checkoutId, r;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
checkoutId = dispatch((0, util_1.getLocalStorageItem)(exports.CHECKOUT_ID_LOCAL_STORAGE_NAME));
if (!checkoutId) {
return [2 /*return*/, (0, api_1.newXcapJsonResult)('success', {
checkout: null
})];
}
if (!imageMaxWidth) {
imageMaxWidth = getState().shop.defaults.imageMaxWidth;
}
return [4 /*yield*/, dispatch((0, index_1.getCheckout)({ checkoutId: checkoutId, imageMaxWidth: imageMaxWidth }))];
case 1:
r = _a.sent();
if (!(!r.error && r.checkout)) return [3 /*break*/, 4];
if (!r.checkout.completedAt) return [3 /*break*/, 2];
// Checkout is turned into an order. Remove
dispatch((0, exports.clearCheckout)());
return [3 /*break*/, 4];
case 2:
handleCheckoutProductData(dispatch, r.checkout);
return [4 /*yield*/, dispatch({
type: shopReducer_1.RECEIVE_CHECKOUT,
checkoutUserErrors: null,
checkout: r.checkout
})];
case 3:
_a.sent();
_a.label = 4;
case 4: return [2 /*return*/, r];
}
});
}); };
};
exports.requestOrResetActiveCheckout = requestOrResetActiveCheckout;
/**
* Handle product data received via checkout:
* Adds the products to the store and tranforms the returned data
* @param dispatch
* @param checkout
*/
function handleCheckoutProductData(dispatch, checkout) {
if (!checkout) {
return false;
}
var products = {};
var lineItems = { edges: [] };
(0, graphql_1.forEachGraphQLList)(checkout.lineItems, function (i) {
var p = i.variant.product;
// Contains extra product data
if (typeof p['availableForSale'] === 'boolean') {
var product = p;
products[product.handle] = product;
// Remove the extra data
var li = {
node: {
id: i.id,
quantity: i.quantity,
title: i.title,
variant: {
id: i.variant.id,
product: {
id: i.variant.product.id,
handle: i.variant.product.handle
}
}
}
};
lineItems.edges.push(li);
}
else {
lineItems.edges.push({ node: i });
}
});
checkout.lineItems = lineItems;
if (Object.keys(products).length === 0) {
return false;
}
dispatch({
type: shopReducer_1.RECEIVE_MULTIPLE_PRODUCTS,
json: (0, api_1.newXcapJsonResult)('success', {
products: products
})
});
return true;
}
/**
* Add an item to the checkout. Possibly creating a new checkout.
* @param product
* @param variant
* @param quantity
*/
var checkoutAdd = function (product, variant, quantity) {
return function (dispatch, getState) { return __awaiter(void 0, void 0, void 0, function () {
var q, shop, lineItems, r;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!product || !variant) {
throw new Error('product and variant required');
}
q = quantity || 1;
shop = getState().shop;
lineItems = addItem(toLineItemArray(shop.checkout), variant.id, q);
return [4 /*yield*/, dispatch((0, exports.checkoutUpdateOrCreateNew)(shop, lineItems, product.handle, variant.id, quantity || 1))];
case 1:
r = _a.sent();
if (!r.error) {
dispatch({ type: shopReducer_1.ADD_TO_BASKET, product: product, variant: variant, variantId: variant.id, quantity: q });
}
return [2 /*return*/, r];
}
});
}); };
};
exports.checkoutAdd = checkoutAdd;
/**
* Remove a item from the checkout, possibly creating a new checkout
* @param product
* @param variant
* @param quantity
*/
var checkoutRemove = function (product, variant, quantity) {
return function (dispatch, getState) { return __awaiter(void 0, void 0, void 0, function () {
var shop, q, lineItems, r;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!product || !variant) {
throw new Error('product and variant required');
}
shop = getState().shop;
q = quantity || 1;
lineItems = removeItem(toLineItemArray(shop.checkout), variant.id, q);
return [4 /*yield*/, dispatch((0, exports.checkoutUpdateOrCreateNew)(shop, lineItems))];
case 1:
r = _a.sent();
if (!r.error) {
dispatch({ type: shopReducer_1.REMOVE_FROM_BASKET, product: product, variant: variant, variantId: variant.id, quantity: q });
}
return [2 /*return*/, r];
}
});
}); };
};
exports.checkoutRemove = checkoutRemove;
/**
* Set quantity of an item.
* @param variantId
* @param quantity
*/
var checkoutSetQuantity = function (variantId, quantity) {
return function (dispatch, getState) { return __awaiter(void 0, void 0, void 0, function () {
var shop, lineItems;
return __generator(this, function (_a) {
shop = getState().shop;
lineItems = setItemQuantity(toLineItemArray(shop.checkout), variantId, quantity);
return [2 /*return*/, dispatch((0, exports.checkoutUpdateOrCreateNew)(shop, lineItems))];
});
}); };
};
exports.checkoutSetQuantity = checkoutSetQuantity;
/**
* Update the items in the checkout. Create a new checkout if needed.
* @param shop
* @param lineItems
* @param addedProductHandle
* @param variantId
* @param quantity
*/
var checkoutUpdateOrCreateNew = function (shop, lineItems, addedProductHandle, variantId, quantity) {
return function (dispatch) { return __awaiter(void 0, void 0, void 0, function () {
var r;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!(shop.checkout === null || shop.checkout.completedAt !== null)) return [3 /*break*/, 2];
return [4 /*yield*/, dispatch(createCheckout({
input: {
lineItems: lineItems
},
addedProductHandle: addedProductHandle,
variantId: variantId,
quantity: quantity
}))];
case 1:
r = _a.sent();
return [3 /*break*/, 4];
case 2: return [4 /*yield*/, dispatch((0, exports.checkoutReplaceItems)({
checkoutId: shop.checkout.id,
lineItems: lineItems,
addedProductHandle: addedProductHandle,
variantId: variantId,
quantity: quantity
}))];
case 3:
r = _a.sent();
_a.label = 4;
case 4:
if (!r.error) {
dispatch({ type: shopReducer_1.BASKET_UPDATED });
}
return [2 /*return*/, r];
}
});
}); };
};
exports.checkoutUpdateOrCreateNew = checkoutUpdateOrCreateNew;
/**
* Given a CheckoutLineItem, find the corresponding product variant
* @param shop
* @param item
*/
function getProductAndVariant(shop, item) {
return getProductAndVariant2(shop, item.variant.product.handle, item.variant.id);
}
exports.getProductAndVariant = getProductAndVariant;
/**
* Given a product handle and variantId, find the corresponding product variant
* @param shop
* @param productHandle
* @param variantId
*/
function getProductAndVariant2(shop, productHandle, variantId) {
var products = shop.products;
var product = products[productHandle];
if (!product) {
return null;
}
var n = product.variants.edges.find(function (n) { return n.node.id === variantId; });
if (!n) {
return null;
}
return {
product: product,
variant: n.node
};
}
exports.getProductAndVariant2 = getProductAndVariant2;
/**
* Convert the line items of the checkout to an array suitable
* for calling the various functions
* @param checkout
*/
function toLineItemArray(checkout) {
if (!checkout || !checkout.lineItems) {
return [];
}
return (0, graphql_1.mapGraphQLList)(checkout.lineItems, function (i) {
return {
variantId: i.variant.id,
quantity: i.quantity
};
});
}
exports.toLineItemArray = toLineItemArray;
/**
* Add line items
* @param items
* @param variantId
* @param quantity
*/
function addItem(items, variantId, quantity) {
var item = items.find(function (i) { return i.variantId == variantId; });
if (item) {
item.quantity += quantity || 1;
}
else {
items.push({
variantId: variantId,
quantity: quantity || 1
});
}
return items.filter(function (i) { return i.quantity > 0; });
}
exports.addItem = addItem;
/**
* Remove line items
* @param items
* @param variantId
* @param quantity
*/
function removeItem(items, variantId, quantity) {
var item = items.find(function (i) { return i.variantId == variantId; });
if (item) {
item.quantity -= quantity || 1;
}
return items.filter(function (i) { return i.quantity > 0; });
}
exports.removeItem = removeItem;
/**
* Set item quantity
* @param items
* @param variantId
* @param quantity
*/
function setItemQuantity(items, variantId, quantity) {
var item = items.find(function (i) { return i.variantId == variantId; });
if (item) {
item.quantity = quantity;
}
else {
items.push({
variantId: variantId,
quantity: quantity
});
}
return items.filter(function (i) { return i.quantity > 0; });
}
exports.setItemQuantity = setItemQuantity;
/**
* Replace the items in the checkout
* @param req
*/
var checkoutReplaceItems = function (req) {
return function (dispatch) { return __awaiter(void 0, void 0, void 0, function () {
var r;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, , 5, 7]);
return [4 /*yield*/, dispatch((0, throbberActions_1.setModalThrobberVisible)(true))];
case 1:
_a.sent();
return [4 /*yield*/, dispatch((0, index_1.checkoutReplaceItems)(req))];
case 2:
r = _a.sent();
if (!!hasCheckoutErrors(r)) return [3 /*break*/, 4];
return [4 /*yield*/, dispatch({
type: shopReducer_1.RECEIVE_CHECKOUT,
checkoutUserErrors: r.response.checkoutUserErrors,
checkout: r.response.checkout
})];
case 3:
_a.sent();
_a.label = 4;
case 4: return [2 /*return*/, r];
case 5: return [4 /*yield*/, dispatch((0, throbberActions_1.setModalThrobberVisible)(false))];