@craftercms/studio-ui
Version:
Services, components, models & utils to build CrafterCMS authoring extensions.
178 lines (176 loc) • 6.9 kB
JavaScript
/*
* Copyright (C) 2007-2022 Crafter Software Corporation. All Rights Reserved.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3 as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Copyright (C) 2007-2022 Crafter Software Corporation. All Rights Reserved.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
var __rest =
(this && this.__rest) ||
function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === 'function')
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]];
}
return t;
};
import { configureStore } from '@reduxjs/toolkit';
import reducer from './reducers/root';
import { createEpicMiddleware } from 'redux-observable';
import epic from './epics/root';
import { BehaviorSubject, forkJoin, fromEvent, Observable, of } from 'rxjs';
import { filter, map, pluck, switchMap, take, tap } from 'rxjs/operators';
import { fetchGlobalProperties, me } from '../services/users';
import { exists, fetchAll } from '../services/sites';
import { getCurrentIntl } from '../utils/i18n';
import { getSiteCookie, removeSiteCookie, setJwt } from '../utils/auth';
import { storeInitialized } from './actions/system';
import {
sharedWorkerConnect,
sharedWorkerDisconnect,
sharedWorkerToken,
sharedWorkerUnauthenticated
} from './actions/auth';
import { SHARED_WORKER_NAME } from '../utils/constants';
import { fetchActiveEnvironment } from '../services/environment';
let store$;
export function getStore() {
if (store$) {
return store$.pipe(
filter((store) => store !== null),
take(1)
);
} else {
store$ = new BehaviorSubject(null);
return registerSharedWorker().pipe(
tap(({ token }) => setJwt(token)),
switchMap((_a) => {
var { worker } = _a,
auth = __rest(_a, ['worker']);
return of(createStoreSync({ dependencies: { worker } })).pipe(
switchMap((store) =>
fetchStateInitialization().pipe(
tap((requirements) => {
worker.port.onmessage = (e) => {
var _a;
if ((_a = e.data) === null || _a === void 0 ? void 0 : _a.type) {
store.dispatch(e.data);
}
};
store.dispatch(storeInitialized(Object.assign({ auth }, requirements)));
store$.next(store);
})
)
)
);
}),
switchMap(() => store$.pipe(take(1)))
);
}
}
function registerSharedWorker() {
if ('SharedWorker' in window) {
const worker = new SharedWorker(`${process.env.PUBLIC_URL}/shared-worker.js`, {
name: SHARED_WORKER_NAME,
credentials: 'same-origin'
});
worker.port.start();
worker.port.postMessage(sharedWorkerConnect());
window.addEventListener('beforeunload', function () {
worker.port.postMessage(sharedWorkerDisconnect());
});
return fromEvent(worker.port, 'message').pipe(
tap((e) => {
var _a;
if (((_a = e.data) === null || _a === void 0 ? void 0 : _a.type) === sharedWorkerUnauthenticated.type) {
const elem = document.createElement('div');
elem.style.textAlign = 'center';
elem.style.margin = '20px 0';
elem.innerHTML = 'User not authenticated.';
setTimeout(() => {
window.location.reload();
}, 800);
throw new Error('User not authenticated.');
}
}),
filter((e) => {
var _a;
return ((_a = e.data) === null || _a === void 0 ? void 0 : _a.type) === sharedWorkerToken.type;
}),
take(1),
pluck('data', 'payload'),
map((response) => Object.assign(Object.assign({}, response), { worker }))
);
} else {
return new Observable((observer) => {
observer.error(
['iPad Simulator', 'iPhone Simulator', 'iPod Simulator', 'iPad', 'iPhone', 'iPod'].includes(navigator.platform)
? 'iOS is not supported as it lacks essential features. Please use Chrome or Firefox browsers on your desktop.'
: 'Your browser is not supported as it lacks essential features. Please use Chrome or Firefox.'
);
});
}
}
export function getStoreSync() {
return store$ === null || store$ === void 0 ? void 0 : store$.value;
}
export function createStoreSync(args = {}) {
const { preloadedState, dependencies } = args;
const epicMiddleware = createEpicMiddleware({
dependencies: Object.assign({ getIntl: getCurrentIntl }, dependencies)
});
const store = configureStore({
reducer,
middleware: (getDefaultMiddleware) => getDefaultMiddleware({ thunk: false }).concat(epicMiddleware),
preloadedState,
devTools: { name: 'Studio Store' }
// devTools: process.env.NODE_ENV === 'production' ? false : { name: 'Studio Store' }
});
epicMiddleware.run(epic);
return store;
}
export function fetchStateInitialization() {
const siteCookieValue = getSiteCookie();
return forkJoin({
user: me(),
sites: fetchAll(),
properties: fetchGlobalProperties(),
activeSiteId:
// A site cookie may be set but the site may have been deleted.
// If there is a cookie with a site name, verify that it still exists.
siteCookieValue
? exists(siteCookieValue).pipe(
// If the site doesn't exist, delete the cookie so it doesn't cause further issues
tap((siteExists) => !siteExists && removeSiteCookie()),
map((siteExists) => (siteExists ? siteCookieValue : null))
)
: of(null),
activeEnvironment: fetchActiveEnvironment()
});
}
export default getStore;