Repository URL to install this package:
|
Version:
0.0.15 ▾
|
import * as tslib_1 from "tslib";
// modules/libs
import { oneRouter } from '@skava/router';
import { isString } from 'exotic';
import { when, computed } from 'xmobx/mobx';
// import * as cookiez from '@skava/cookies'
// import {
// has as hasCookie,
// get as getCookie,
// renewCache,
// config as cookieLibConfig,
// } from '@skava/cookies'
import { cookies } from '@skava/cookies';
import { isErrorLikeResponse } from '@skava/is-error-like-response';
import { ObservableContainer } from '@skava/packages/libraries/observable-container';
// ===========================
// state... SHOULD NOT IMPORT SO MANY IN HERE, ENSURE THEY DO NOT IMPORT EACH OTHER
// @example @issue before
// session <====> cart
// session <====> shoppingList
// ===========================
// @note => user/payments => session
import { userContainer } from '@skava/packages/core/auth/user/container';
import { toastMessage, responseMessage } from '@skava/packages/core/notifications';
import { errorContainer } from '@skava/packages/core/notifications';
// ========= @@packages @@modularization @@modules ===
// was importing this, changed to .apis as a split to avoid that
import { cartContainer } from '@skava/packages/core/cart/state/containers';
import { listContainer, listContainerApi, saveForLaterContainer, shoppingListContainer, favoritesContainer, } from '@skava/packages/features/Lists/state';
import { authenticationSwitchContainer } from '@skava/packages/features/Authentication/container';
// ========= @@packages @@modularization @@modules ===
// domain config
import { cookieConfig } from 'src/bootstrap/api/config';
import { config as appConfig } from 'src/bootstrap/config';
import { sessionApis } from './container.apis';
import { toStatus, fromResponseToLoginToast, toSyncListResponse, checkIsSessionExpired, isRegisterSuccess, toBagResponse, toFavoritesResponse, toSaveForLaterResponse, mapCookiesOnResponse, isLoginSuccess, createRecentlyViewedList, toUserProfileResponse, clearCookies, checkSessionExpiredOnMyAccount, } from './deps';
import { logoutBinding } from './bindings';
// issue with v4 cookies
if (typeof window === 'object') {
// cookieLibConfig.set('document', document)
// renewCache()
window.Cookiez = cookies;
}
const hasCookie = cookies.has;
const getCookie = cookies.get;
const renewCache = cookies.renewCache;
class SessionContainer extends ObservableContainer {
constructor() {
super(...arguments);
this.navigateBackTo = '';
this.registerUser = async (data, securityParams) => {
const user = await sessionApis
.registerUser(data, securityParams)
// .then(this.mapCookiesOnResponse)
// .then(() => {
// // now this happens 2x
// sessionApis.createList().then(toListResponse)
// sessionApis.createSaveForLater().then(toListResponse)
// sessionApis.viewBag().then(toBagResponse)
// })
.then(this.handleRegisterResponse)
.catch(this.handleError);
/**
* @todo this should be an array @@perf
*/
let profile = '';
let security = '';
const userStatus = toStatus(user);
if (userStatus === responseMessage.accountCreationSuccess ||
userStatus === responseMessage.registerMailFailure) {
profile = await userContainer
.fetchUserLiteProfile()
.then(toUserProfileResponse)
.then(async (response) => {
if (this.isRegisteredUser) {
console.log('registerUser createSaveForLaterList');
await this.getAllListAPI();
}
console.log('Loaded User Profile');
userContainer.updateFrom(response);
// this.omniStore.loadUser(response)
this.navigateToLoginSuccess();
})
.catch(this.handleError);
if (process.env.API_LAYER === 'Stream') {
security = await sessionApis.updateSecurity(securityParams, true);
}
// .then((response: unknown) => {
// console.log('security Question response', response)
// userContainer.updateFrom(response)
// })
}
// may not want to do it this way
// may want to show a loader in interfacestore
// & then go to the other page
// oneRouter.replace('/myaccount')
return Promise.all([user, profile, security]).then(result => {
console.log(result);
});
};
this.getAllListAPI = async () => {
const response = await listContainerApi.getAllList().then((listResponse) => {
favoritesContainer.checkAndUpdateFavorites(listResponse);
shoppingListContainer.updateFrom(listResponse);
saveForLaterContainer.createSaveForLaterList(listResponse);
});
return response;
};
/**
* @todo @fixme this is to be done on graphql side!!!
*/
this.adminRegisterAccount = async (data) => {
const registerData = {
firstName: data['first-name'],
lastName: data['last-name'],
phoneNumber: data['phone-number'],
email: data.email,
name: data['organization-name'],
// password: '',
street1: data['address-line-one'],
street2: data['address-line-two'] || '',
street3: '',
city: data.city,
country: data.country,
state: data.state,
county: '',
zipCode: data.postalCode,
taxId: data['tax-identifier'],
dunsNumber: isString(data.duns) ? data.duns : '',
};
const response = await sessionApis.adminRegisterAccount(registerData);
if (isErrorLikeResponse(response)) {
errorContainer.setError({
errorMessage: response.responseMessage || '',
});
}
else {
oneRouter.update('/');
errorContainer.setError({
errorMessage: toastMessage.registerSuccess,
});
}
};
this.updateProfile = async (profileData) => {
const response = await sessionApis.updateProfile(profileData).catch(this.handleError);
this.fetchProfile();
return response;
// .then(this.fetchProfile)
};
this.updateSecurity = async (data) => {
const response = await sessionApis.updateSecurity(data).catch(this.handleError);
return response;
};
this.getSecurityQuestions = async (data) => {
const response = await sessionApis.getSecurityQuestions(data).catch(this.handleError);
return response;
};
this.resetPasswordThroughSms = async (data) => {
const response = await sessionApis.resetPasswordThroughSms(data).catch(this.handleError);
return response;
};
this.resetPasswordThroughEmail = async (data) => {
const response = await sessionApis.resetPasswordThroughEmail(data).catch(this.handleError);
return response;
};
this.validateByEmail = async (data) => {
const response = await sessionApis.validateByEmail(data).catch(this.handleError);
return response;
};
this.userActivation = async (data) => {
const response = await sessionApis.userActivation(data).catch(this.handleError);
return response;
};
this.resetPasswordThroughSecurityQuestions = async (data) => {
const response = await sessionApis
.resetPasswordThroughSecurityQuestions(data)
.catch(this.handleError);
return response;
};
this.updatePassword = async (password) => {
const response = await sessionApis.updatePassword(password).catch(this.handleError);
return response;
};
// @todo - use routes here so it is configurable in 1 place
this.registerGuestUser = async () => {
if (this.isOrchestrationGuestUser || this.isGuestUser) {
console.log('Already a guest!');
return false;
}
else {
console.log('No active user found creating guest');
const guest = await sessionApis.registerGuestUser();
const profile = await userContainer
.fetchUserLiteProfile()
.then(toUserProfileResponse)
.then((response) => {
userContainer.updateFrom(response);
})
.then(createRecentlyViewedList);
await favoritesContainer.createFavoritesList();
await saveForLaterContainer.createDefaultListForSave();
return Promise.all([guest, profile]).then(result => {
if (typeof window === 'object') {
console.log('[Cookie Monster]', 'Registered Guest User', window.document.cookie);
}
// return result
});
}
};
/**
* @todo show toast
*/
this.logOut = async () => {
const response = await logoutBinding();
clearCookies();
// oneRouter.replace('/logout')
// oneRouter.reload()
errorContainer.setError({
errorMessage: 'Signed out',
});
// window.location.reload()
// return response.data.logOut
};
this.handleLoginResponse = (response) => {
const isLoginSuccessful = isLoginSuccess(response);
if (isLoginSuccessful) {
// console.log('You are logged in')
// errorContainer.setMessage('Successfully signed in')
mapCookiesOnResponse(response);
// @todo this code used for clearing favorites of guest when signed in
// remove this code when list merge is implemented
// ^ @jai
// favoritesContainer.removeFromFavorites()
}
else {
authenticationSwitchContainer.gotoFreezeSignIn(response);
const toastText = fromResponseToLoginToast(response);
errorContainer.setError({
errorMessage: toastText,
});
console.log('Something Strange In The Neighborhood', response);
}
return isLoginSuccessful;
};
this.handleRegisterResponse = (response) => {
// @todo use isErrorLikeResponse to check response success/Failure
if (isRegisterSuccess(response)) {
favoritesContainer.createFavoritesList();
saveForLaterContainer.createDefaultListForSave();
// @todo remove this after cart and list merge done @gokul
// ^ commented out @james @@packages
// cartContainer.fetched.hasFetchedSaveForLater = false
// cartContainer.viewCart()
console.log('User created Successfully');
}
else {
errorContainer.setError({
errorMessage: toStatus(response) || '',
});
console.log('Something Strange In The User creation', response);
}
return response;
};
this.logIn = async (data) => {
if (this.isRegisteredUser) {
errorContainer.setMessage('Already signed in');
this.navigateToLoginSuccess();
return true;
}
const loginUser = await sessionApis
.logIn(data)
.then(this.handleLoginResponse)
.catch(this.handleError);
const withProfile = await userContainer
.fetchUserLiteProfile()
.then(toUserProfileResponse)
.then(async (response) => {
if (this.isRegisteredUser) {
console.log('logIn createSaveForLaterList');
await this.getAllListAPI();
// to fetch save for later again moving from guest flow to signed in
// cartContainer.fetched.hasFetchedSaveForLater = false
cartContainer.viewCart();
}
userContainer.updateFrom(response);
// @note this is different than others
// when we load user then return response
// this.omniStore.loadUser(response)
})
.then(() => {
this.navigateToLoginSuccess();
return true;
})
.catch(this.handleError);
/**
* @see https://jira.skava.net/browse/SKB2B-2403
*/
return Promise.all([loginUser, withProfile]).then(result => {
return result[0];
// console.log('Logged In')
});
};
this.loginWithFacebook = async (data) => {
if (this.isRegisteredUser) {
this.navigateToLoginSuccess();
console.log('You are already logged in');
return;
}
await sessionApis
.loginWithFacebook(data)
.then(this.handleLoginResponse)
// @todo if this fails, don't fetch?
.catch(this.handleError);
await this.fetchProfile();
this.navigateToLoginSuccess();
};
this.loginWithTwitter = async (data) => {
if (this.isRegisteredUser) {
this.navigateToLoginSuccess();
console.log('You are already logged in');
return;
}
let loginResponse = '';
await sessionApis
.loginWithTwitter(data)
.then((response) => {
loginResponse = response;
this.handleLoginResponse(response);
})
// @todo if this fails, don't fetch?
.catch(this.handleError);
await this.fetchProfile();
if (isLoginSuccess(loginResponse)) {
this.navigateToLoginSuccess(true);
}
};
this.loginWithGoogle = async (data) => {
if (this.isRegisteredUser) {
this.navigateToLoginSuccess();
console.log('You are already logged in');
return;
}
await sessionApis
.loginWithGoogle(data)
.then(this.handleLoginResponse)
// @todo if this fails, don't fetch?
.catch(this.handleError);
await this.fetchProfile();
this.navigateToLoginSuccess();
};
this.getTokenAuth = async () => {
const response = await sessionApis.getTwitterAuthToken();
return response;
};
// shouldEnablePaymentRetrival, shouldEnableAddressRetrival
this.fetchProfile = async () => {
const profile = await userContainer
.fetchUserLiteProfile()
.then(toUserProfileResponse)
// @todo inline, but not sure on resolved result
.then((response) => {
userContainer.updateFrom(response);
if (response.responseCode === '401') {
clearCookies();
}
// this.omniStore.loadUser(response)
return response;
})
.catch(this.handleError);
/**
* Session expired check and navigation to the /signin page
* in the user profile call
*/
checkSessionExpiredOnMyAccount(profile);
return Promise.resolve(profile);
};
/**
* @desc this is in parallel, to not block requests
*/
this.afterRegisterUser = async () => {
// sessionApis.createList().then(toListResponse)
// sessionApis.createSaveForLater().then(toListResponse)
cartContainer
.viewCart()
.then(toBagResponse)
.then((response) => {
cartContainer.updateFrom(response);
});
};
/**
* moved out of flow to avoid guarenteed deopt
*/
this._flow = async () => {
const isNotLoggedIn = !this.isOrchestrationGuestUser || !this.isGuestUser || !this.isRegisteredUser;
// const { listStore } = this.omniStore
// @todo
// const lastFlow = localStorage.get('last_flow')
// const now = Date.now()
// let diff = diffInMinutes(lastSaveTime, now)
// if (diff < 5) {
// return ls.get('flow')
// }
// if (isNotLoggedIn) {
// console.log('Not Logged In - Creating Guest User')
// await this.registerGuestUser().then(this.afterRegisterUser)
// }
await when(() => isNotLoggedIn, () => this.registerGuestUser()
/**
* @see https://jira.skava.net/browse/SECTEM-5129
*/
// .then(this.afterRegisterUser)
);
// @todo - why is thi not being done?
// await sessionApis.fetchUserProfile()
/**
* @todo ========= needs to heavily cache here
*
* @note, async will make it blocking, promise.all may be best
*/
await when(() => this.isGuestUser || this.isRegisteredUser, () => {
return sessionApis.fetchList().then(toSyncListResponse);
// .then(this.omniStore.loadLists)
});
await when(() => isString(listContainer.favoriteListId) === true, () => {
return (sessionApis
.fetchListItems(listContainer.favoriteListId)
.then(toFavoritesResponse)
// .then(this.omniStore.loadFavorites)
.catch(this.handleError));
});
await when(() => isString(listContainer.saveForLaterListId) === true, () => {
return (sessionApis
.fetchListItems(listContainer.saveForLaterListId)
.then(toSaveForLaterResponse)
// .then(this.omniStore.loadSaveForLater)
.catch(this.handleError));
});
// @michael
// @todo
// 1. then need to connect this with fixture/graphql
// 2. and set events to update
// 3. these could also be set individually per store
// or we can use graphql.readQuery but here
// we don't have graphql for these calls so
// we can also connect oneStorage to check graphql cache
// through a single interface (@example cache.has checks graphql)
//
// localStorage.set('last_flow', now)
// localStorage.set('flow', {
// viewBag,
// storeCredit,
// favoritesList,
// })
};
/**
* @see https://github.com/petkaantonov/bluebird/wiki/Optimization-killers
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/try...catch
* @see https://github.com/aretecode/awesome-deopt
* ^ regarding try catch issues
*/
this.flow = async () => {
try {
await this._flow();
}
catch (error) {
console.error(error);
throw new Error('API Failed');
}
};
}
get guestUserCookie() {
console.log('[COOKIE_CONFIG]', cookieConfig);
return getCookie(cookieConfig.guest);
}
get hasGuestUserCookie() {
return hasCookie(cookieConfig.guest);
}
get hasOrchestrationGuestUserCookie() {
return hasCookie(cookieConfig.orchestrationGuest);
}
/**
* @@packages @james may want to change this flow because session should not import user?
*/
get isGuestUser() {
return this.hasGuestUserCookie || !!userContainer.firstName || !!userContainer.userName;
}
get isOrchestrationGuestUser() {
return this.hasOrchestrationGuestUserCookie;
}
get isRegisteredUser() {
return this.hasUserCookie || !!userContainer.firstName || !!userContainer.userName;
}
get hasUserCookie() {
return hasCookie(cookieConfig.registered);
}
get userCookie() {
return getCookie(cookieConfig.registered);
}
// or could force only via props?
get userName() {
return this.userCookie || userContainer.userName;
}
get isBuyerAdminUser() {
return getCookie(cookieConfig.buyerAdminNamespace) === 'ROLE_ACCOUNT_BUYER_ADMIN';
}
get isBuyerUser() {
return getCookie(cookieConfig.buyerAdminNamespace) === 'ROLE_BUYER';
}
/**
* @desc much better perf to bind early
* @see https://mobx.js.org/best/react-performance.html#bind-functions-early
*/
handleError(error) {
console.error(error);
}
navigateToLoginSuccess(isFromTwitter) {
const pathParams = appConfig.get('pathParams');
if (this.isRegisteredUser || isFromTwitter) {
if (this.navigateBackTo) {
console.debug('[navigateToLoginSuccess] going back to a previous link');
oneRouter.update(this.navigateBackTo);
this.navigateBackTo = '';
}
// normal login and register success flow
else if (this.isBuyerAdminUser) {
console.debug('[navigateToLoginSuccess] going to my account [b2b]');
oneRouter.update(pathParams.myaccountDashboard);
}
else if (oneRouter.get('pathname') !== '/checkout') {
console.debug('[navigateToLoginSuccess] going to my account');
oneRouter.update(pathParams.myaccountLanding || '/myaccount/welcome');
}
}
}
}
SessionContainer.debugName = 'Session';
tslib_1.__decorate([
computed
], SessionContainer.prototype, "guestUserCookie", null);
tslib_1.__decorate([
computed
], SessionContainer.prototype, "hasGuestUserCookie", null);
tslib_1.__decorate([
computed
], SessionContainer.prototype, "hasOrchestrationGuestUserCookie", null);
tslib_1.__decorate([
computed
], SessionContainer.prototype, "isGuestUser", null);
tslib_1.__decorate([
computed
], SessionContainer.prototype, "isOrchestrationGuestUser", null);
tslib_1.__decorate([
computed
], SessionContainer.prototype, "isRegisteredUser", null);
tslib_1.__decorate([
computed
], SessionContainer.prototype, "hasUserCookie", null);
tslib_1.__decorate([
computed
], SessionContainer.prototype, "userCookie", null);
tslib_1.__decorate([
computed
], SessionContainer.prototype, "userName", null);
tslib_1.__decorate([
computed
], SessionContainer.prototype, "isBuyerAdminUser", null);
tslib_1.__decorate([
computed
], SessionContainer.prototype, "isBuyerUser", null);
const sessionContainer = new SessionContainer();
export default sessionContainer;
export { sessionContainer, SessionContainer, sessionApis, mapCookiesOnResponse, checkIsSessionExpired, checkSessionExpiredOnMyAccount, };
//# sourceMappingURL=container.js.map