UNPKG

@apicart/store-sdk

Version:

Apicart SDK for integrating store into any web application

238 lines (189 loc) 6.82 kB
import Apicart from '@apicart/core-sdk'; import { CartDaoInterface } from '../../Contract/Dao/Cart/CartDaoInterface'; import { DataSourceInterface } from '../../Contract/DataSource/DataSourceInterface'; import Cart from '../../Entity/Cart/Cart'; import CartState from '../../Entity/Cart/CartState'; import { CustomerDaoInterface } from '../../Contract/Dao/Customer/CustomerDaoInterface'; import CustomerDao from '../Customer/CustomerDao'; import { OrderDaoInterface } from '../../Contract/Dao/Order/OrderDaoInterface'; import OrderDao from '../Order/OrderDao'; import CartItem from '../../Entity/Cart/CartItem'; import CartItemParameter from '../../Entity/Cart/CartItemParameter'; import CartParameter from '../../Entity/Cart/CartParameter'; import CartEventDispatcherEvents from '../../EventDispatcherEvents/CartEventDispatcherEvents'; export default class CartDao implements CartDaoInterface { private _hash: string | null = null private _dataSource: DataSourceInterface; private _cart: Cart | null = null; private _cartPromise: Promise<Cart | null> | null = null; constructor(dataSource: DataSourceInterface, hash: string = null) { this._dataSource = dataSource; this._hash = hash; } /** @inheritdoc */ public async getEntity(clearCache = false): Promise<Cart | null> { if (!this._cartPromise && (this._cart === null || clearCache)) { let cart: any = this._cart; this._cartPromise = this.callDataSource((): Promise <Cart | null> => { return this._dataSource.findCart(this.getHash()); }); cart = await this._cartPromise; if (cart === null && this.getHash()) { Apicart.Utils.Console.error('Cart entity with hash "' + this.getHash() + '" not found.'); } else { this._cart = cart; this._hash = cart.getHash(); Apicart.Utils.EventDispatcher.dispatchEvent(CartEventDispatcherEvents.UPDATED, this); } } if (this._cartPromise) { await this._cartPromise; this._cartPromise = null; } return this._cart; } /** @inheritdoc */ public getHash(): string { return this._hash; } /** @inheritdoc */ public async getCreatedAt(): Promise<Date> { return (await this.getEntity()).getCreatedAt(); } /** @inheritdoc */ public async getUpdatedAt(): Promise<Date> { return (await this.getEntity()).getUpdatedAt(); } /** @inheritdoc */ public async getTotalPrice(): Promise<number> { return (await this.getEntity()).getTotalPrice(); } /** @inheritdoc */ public async getCartState(): Promise<CartState> { return (await this.getEntity()).getCartState(); } /** @inheritdoc */ public async getCustomer(): Promise<CustomerDaoInterface> { const customerHash = (await this.getEntity()).getCustomer().getHash(); return new CustomerDao(this._dataSource, customerHash); } /** @inheritdoc */ public async finish(): Promise<OrderDaoInterface> { const response = await this.callDataSource(async (): Promise<OrderDaoInterface> => { const order = await this._dataSource.finishCart(this.getHash()); return order === null ? null : new OrderDao(this._dataSource, order.getHash()); }); Apicart.Utils.EventDispatcher.dispatchEvent(CartEventDispatcherEvents.FINISHED, response); return response; } /** @inheritdoc */ public async addItem(dataUrl: string, quantity = 1, parameters: Record<string, any> = {}): Promise<boolean> { const cartItemParameters = []; Apicart.Utils.Loops.forEach(parameters, (value: any, key: string): void => { if (value instanceof CartItemParameter) { cartItemParameters.push(value); } else { cartItemParameters.push(new CartItemParameter(key, value)); } }); const itemFromCart = await this.findItemByDataUrl(dataUrl); const response = await this.callDataSource(async (): Promise<boolean> => { return this._dataSource.addCartItem(this.getHash(), dataUrl, quantity, cartItemParameters); }, true); const processedItem = await this.findItemByDataUrl(dataUrl); const eventsToDispatch = [ itemFromCart ? CartEventDispatcherEvents.ITEM_UPDATED : CartEventDispatcherEvents.ITEM_ADDED ]; if (itemFromCart) { eventsToDispatch.push( itemFromCart.getQuantity > processedItem.getQuantity ? CartEventDispatcherEvents.ITEM_QUANTITY_DECREASED : CartEventDispatcherEvents.ITEM_QUANTITY_INCREASED ); } Apicart.Utils.EventDispatcher.dispatchEvent(eventsToDispatch, processedItem); return response; } /** @inheritdoc */ public async removeItem(dataUrl: string, quantity: number = null): Promise<boolean> { const response = await this.callDataSource((): Promise<boolean> => { return this._dataSource.removeCartItem(this.getHash(), dataUrl, quantity); }, true); const item = await this.findItemByDataUrl(dataUrl); const itemStillInTheCart = Boolean(item); Apicart.Utils.EventDispatcher.dispatchEvent( itemStillInTheCart ? CartEventDispatcherEvents.ITEM_UPDATED : CartEventDispatcherEvents.ITEM_REMOVED, item ); return response; } public async findItemByDataUrl(dataUrl: string): Promise<CartItem|null> { return (await this.getEntity()).findItemByDataUrl(dataUrl); } /** @inheritdoc */ public async getItems(): Promise<CartItem[]> { return (await this.getEntity()).getItems(); } /** @inheritdoc */ public async addParameter(key: string, value: any): Promise<boolean> { const parameter = {}; parameter[key] = value; return this.addParameters(parameter); } /** @inheritdoc */ public async addParameters(parameters: Record<string, any>): Promise<boolean> { const response = await this.callDataSource((): Promise<boolean> => { return this._dataSource.addCartParameters(this.getHash(), parameters); }, true); Apicart.Utils.EventDispatcher.dispatchEvent(CartEventDispatcherEvents.PARAMETER_ADDED, parameters); return response; } /** @inheritdoc */ public async removeParameter(key: string): Promise<boolean> { return this.removeParameters([key]); } /** @inheritdoc */ public async removeParameters(keys: string[]): Promise<boolean> { const response = await this.callDataSource((): Promise<boolean> => { return this._dataSource.removeCartParameters(this.getHash(), keys); }, true); Apicart.Utils.EventDispatcher.dispatchEvent(CartEventDispatcherEvents.PARAMETER_REMOVED, keys); return response; } /** @inheritdoc */ public async getParameters(): Promise<CartParameter[]> { return (await this.getEntity()).getParameters(); } /** @inheritdoc */ public async getParameterValue(key: string, defaultValue: any | null = null): Promise<any> { return (await this.getEntity()).getParameterValue(key, defaultValue); } private async callDataSource(callback: Function, updateEntity = false): Promise<any> { const response = await callback.call(this); if (updateEntity) { await this.getEntity(true); } return response; } }