@apicart/store-sdk
Version:
Apicart SDK for integrating store into any web application
238 lines (189 loc) • 6.82 kB
text/typescript
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;
}
}