scrivito
Version:
Scrivito is a professional, yet easy to use SaaS Enterprise Content Management Service, built for digital agencies and medium to large businesses. It is completely maintenance-free, cost-effective, and has unprecedented performance and security.
143 lines (112 loc) • 4.06 kB
text/typescript
import {
InternalError,
ScrivitoError,
never,
onReset,
} from 'scrivito_sdk/common';
import {
createLoadableCollection,
loadableWithDefault,
} from 'scrivito_sdk/loadable';
import { BasicObj, ObjScope, getAllObjsByValueFrom } from 'scrivito_sdk/models';
import { Obj, wrapInAppClass } from 'scrivito_sdk/realm';
export type SiteIdForObjCallback = (obj: Obj) => unknown;
export class UnstableMultiSiteModeOperationError extends ScrivitoError {
constructor(message: string) {
super(message);
}
}
let getUnstableSiteIdForObjCallback: SiteIdForObjCallback | undefined;
export function setUnstableMultiSiteMode(callback: SiteIdForObjCallback): void {
getUnstableSiteIdForObjCallback = callback;
}
export function useUnstableMultiSiteMode(): boolean {
return !!getUnstableSiteIdForObjCallback;
}
export function getUnstableSiteIdForObjId(objId: string) {
if (useUnstableMultiSiteMode()) {
const obj = BasicObj.get(objId);
if (obj) return getSiteIdForObj(obj);
}
return null;
}
function getSiteIdForObj(obj: BasicObj): string | null {
const siteId = getUnstableSiteIdForObjCallback!(wrapInAppClass(obj));
if (typeof siteId === 'string' && siteId.length > 0) {
return siteId;
}
return null;
}
/** Selecting a site ID only makes sense in the unstable multi-site mode */
export function unstable_selectSiteId(siteId: string): void {
if (!getUnstableSiteIdForObjCallback) {
throw new UnstableMultiSiteModeOperationError(
'Scrivito.unstable_selectSiteId is only available in the multi-site mode'
);
}
const preselected = loadableWithDefault(null, getUnstableSelectedSiteId);
if (preselected && preselected !== siteId) {
throw new UnstableMultiSiteModeOperationError(
`Scrivito.unstable_selectSiteId called with ${siteId}, but ${preselected} was already selected`
);
}
if (typeof siteId !== 'string' || !siteId) {
throw new UnstableMultiSiteModeOperationError(
'Scrivito.unstable_selectSiteId can only be called with a non-empty string'
);
}
selectedSiteId().set(siteId);
}
/** Accessing the selected site ID only makes sense in the multi-site mode */
export function getUnstableSelectedSiteId(): string | null {
// This should never happen!
if (!getUnstableSiteIdForObjCallback) {
// Calling getUnstableSelectedSiteId is only available in multi-site mode
throw new InternalError();
}
return selectedSiteId().get() || null;
}
// For test purpose only.
export function resetUnstableMultiSiteMode(): void {
getUnstableSiteIdForObjCallback = undefined;
}
const loadableCollection = createLoadableCollection({
name: 'multiSiteMode',
// the site id is not actually "loaded",
// we are just waiting for the application to set it
loadElement: () => ({
loader: () => never<string>(),
}),
});
function selectedSiteId() {
return loadableCollection.get('selectedSiteId');
}
export function recognizeUnstableMultiSitePermalink(
path: string,
scope: ObjScope
): BasicObj | undefined {
const siteId = getSiteIdAssumingSelected();
const objs = getAllObjsByValueFrom(scope, '_permalink', path);
const matchingObjs = objs.filter((obj) => {
const objSiteId = getSiteIdForObj(obj);
return objSiteId ? objSiteId === siteId : true;
});
const matchingNotDeletedObjs = matchingObjs.filter((obj) => !obj.isDeleted());
return matchingNotDeletedObjs[0] ?? matchingObjs[0];
}
export function isGlobalOrFromUnstableSelectedSite(obj: BasicObj): boolean {
const objSiteId = getSiteIdForObj(obj);
const currentSiteId = getSiteIdAssumingSelected();
return !objSiteId || objSiteId === currentSiteId;
}
function getSiteIdAssumingSelected(): string | null {
const siteId = loadableWithDefault(undefined, getUnstableSelectedSiteId);
if (siteId === undefined) {
throw new ScrivitoError(
'Access to routing in the multi-site mode, but the site ID is not yet selected.' +
' Forgot to use Scrivito.unstable_selectSiteId?'
);
}
return siteId;
}
onReset(resetUnstableMultiSiteMode);