import postRobot from "post-robot";
import EventEmitter from "wolfy87-eventemitter";
import AssetSidebarWidget from "./AssetSidebarWidget";
import { IRTEPluginInitializer } from "./RTE/types";
import { AppConfig } from "./appConfig";
import Entry from "./entry";
import Field from "./field";
import FieldModifierLocationEntry from "./fieldModifierLocation/entry";
import FieldModifierLocationField from "./fieldModifierLocation/field";
import FieldModifierLocationFrame from "./fieldModifierLocation/frame";
import Metadata from "./metadata";
import Modal from "./modal";
import Stack from "./stack";
import Store from "./store";
import {
IAppConfigWidget,
ICustomField,
IDashboardWidget,
IFieldModifierLocation,
IFullPageLocation,
ISidebarWidget,
InitializationData,
LocationType,
Region,
} from "./types";
import { GenericObjectType } from "./types/common.types";
import { User } from "./types/user.types";
import { formatAppRegion, onData, onError } from "./utils/utils";
import Window from "./window";
const emitter = new EventEmitter();
/**
* Class representing an extension from Contentstack App SDK.
* @hideconstructor
*/
class Extension {
/**
* This value represents the current app's unique ID.
*/
appUID: string;
/**
* This holds the app's installation ID.
*/
installationUID: string;
/**
* This object holds details of the current user.
*/
currentUser: User;
/**
* The type of UI Location being rendered.
*/
private type: LocationType;
/**
* The configuration set for an app.
*/
private config: GenericObjectType;
/**
* This holds the instance of Cross-domain communication library for posting messages between windows.
*/
postRobot: typeof postRobot;
/**
* This holds the stack instance that allows users to read and manipulate a range of objects in a stack.
*/
stack: Stack;
/**
* Store to persist data for extension.
* Note: Data is stored in the browser's {@link external:localStorage} and will be lost if the {@link external:localStorage} is cleared in the browser.
*/
store: Store;
/**
* This holds the instance of the Metadata class used to manage metadata.
*/
metadata: Metadata;
/**
* This value represents the current location's unique ID. One App may contain multiple locations
*/
locationUID: string;
/**
* This holds the instance of a helper class used to manage modals in an App.
*/
modal: Modal;
/**
* The Contentstack Region on which the app is running.
*/
readonly region: Region;
/**
* This holds the information of the currently running location of an App.
*/
location: {
DashboardWidget: IDashboardWidget | null;
SidebarWidget: ISidebarWidget | null;
CustomField: ICustomField | null;
RTEPlugin: IRTEPluginInitializer | null;
AppConfigWidget: IAppConfigWidget | null;
AssetSidebarWidget: AssetSidebarWidget | null;
FullPage: IFullPageLocation | null;
FieldModifierLocation: IFieldModifierLocation | null;
};
constructor(initData: InitializationData) {
const initializationData = initData;
this.postRobot = postRobot;
this.appUID = initializationData.app_id;
this.locationUID = initializationData.extension_uid;
this.installationUID = initializationData.installation_uid;
this.currentUser = initializationData.user;
this.type = initializationData.type;
this.store = new Store(postRobot);
this.stack = new Stack(initializationData.stack, postRobot, {
currentBranch: initializationData.currentBranch,
});
this.metadata = new Metadata(postRobot);
this.config = initializationData.config ?? {};
this.location = {
DashboardWidget: null,
CustomField: null,
SidebarWidget: null,
RTEPlugin: null,
AppConfigWidget: null,
AssetSidebarWidget: null,
FullPage: null,
FieldModifierLocation: null,
};
window["postRobot"] = postRobot;
this.modal = new Modal();
this.region = formatAppRegion(initializationData.region);
const stack = new Stack(initializationData.stack, postRobot, {
currentBranch: initializationData.currentBranch,
});
switch (initializationData.type) {
case LocationType.DASHBOARD: {
this.location.DashboardWidget = {
frame: new Window(
postRobot,
this.type as "DASHBOARD",
emitter,
initializationData.dashboard_width
),
stack: new Stack(initializationData.stack, postRobot, {
currentBranch: initializationData.currentBranch,
}),
};
break;
}
case LocationType.WIDGET: {
this.location.SidebarWidget = {
entry: new Entry(initializationData, postRobot, emitter),
stack: new Stack(initializationData.stack, postRobot, {
currentBranch: initializationData.currentBranch,
}),
};
break;
}
case LocationType.APP_CONFIG_WIDGET: {
this.location.AppConfigWidget = {
installation: new AppConfig(
initializationData,
postRobot,
emitter,
{
currentBranch: initializationData.currentBranch,
}
),
stack: new Stack(initializationData.stack, postRobot, {
currentBranch: initializationData.currentBranch,
}),
};
break;
}
case LocationType.ASSET_SIDEBAR_WIDGET: {
this.location.AssetSidebarWidget = new AssetSidebarWidget(
initializationData,
postRobot,
emitter
);
break;
}
case LocationType.RTE: {
import("./RTE").then(({ rtePluginInitializer }) => {
this.location.RTEPlugin = rtePluginInitializer;
});
break;
}
case LocationType.FIELD_MODIFIER_LOCATION: {
initializationData.self = true;
this.location.FieldModifierLocation = {
entry: new FieldModifierLocationEntry(
initializationData,
postRobot,
emitter
),
stack: new Stack(initializationData.stack, postRobot, {
currentBranch: initializationData.currentBranch,
}),
field: new FieldModifierLocationField(
initializationData,
postRobot,
emitter
),
frame: new FieldModifierLocationFrame(postRobot, emitter),
};
break;
}
case LocationType.FULL_PAGE_LOCATION: {
this.location.FullPage = {
stack: stack,
};
break;
}
case LocationType.FIELD:
default: {
initializationData.self = true;
this.location.CustomField = {
field: new Field(initializationData, postRobot, emitter),
fieldConfig: initializationData.field_config,
entry: new Entry(initializationData, postRobot, emitter),
stack: new Stack(initializationData.stack, postRobot, {
currentBranch: initializationData.currentBranch,
}),
frame: new Window(postRobot, this.type as "FIELD", emitter),
};
break;
}
}
try {
postRobot.on("extensionEvent", async (event) => {
if (event.data.name === "entrySave") {
emitter.emitEvent("entrySave", [{ data: event.data.data }]);
emitter.emitEvent("updateFields", [
{ data: event.data.data },
]);
}
if (event.data.name === "entryChange") {
emitter.emitEvent("entryChange", [
{
data: event.data.data,
resolvedData: event.data.otherData.resolvedData,
},
]);
}
if (event.data.name === "entryPublish") {
emitter.emitEvent("entryPublish", [
{ data: event.data.data },
]);
}
if (event.data.name === "entryUnPublish") {
emitter.emitEvent("entryUnPublish", [
{ data: event.data.data },
]);
}
if (event.data.name === "assetSave") {
emitter.emitEvent("assetSave", [{ data: event.data.data }]);
emitter.emitEvent("updateFields", [
{ data: event.data.data },
]);
}
if (event.data.name === "assetChange") {
emitter.emitEvent("assetChange", [
{ data: event.data.data },
]);
}
if (event.data.name === "assetPublish") {
emitter.emitEvent("assetPublish", [
{ data: event.data.data },
]);
}
if (event.data.name === "assetUnPublish") {
emitter.emitEvent("assetUnPublish", [
{ data: event.data.data },
]);
}
if (event.data.name === "dashboardResize") {
emitter.emitEvent("dashboardResize", [
{ state: event.data.state },
]);
}
if (event.data.name === "extensionFieldChange") {
emitter.emitEvent("extensionFieldChange", [
{ data: event.data.data },
]);
}
});
} catch (err) {
console.error("extension Event", err);
}
}
pulse = (eventName: string, metadata: GenericObjectType): void => {
this.postRobot.sendToParent("analytics", { eventName, metadata });
};
/**
* Method used to retrieve the configuration set for an app.
*/
getConfig = (): Promise<GenericObjectType> => {
if (!this.installationUID) {
return Promise.resolve(this.config);
}
return this.postRobot
.sendToParent("getConfig")
.then(onData)
.catch(onError);
};
/**
* Method used to get the type of currently running UI location of the app.
*/
getCurrentLocation = (): LocationType => {
return this.type;
};
/**
* Method used to get the Contentstack Region on which the app is running.
*/
getCurrentRegion = (): Region => {
return this.region;
};
/**
* Method used to initialize the App SDK.
* @param version - Version of the app SDK in use.
*/
static async initialize(version: string): Promise<InitializationData> {
const meta = {
sdkType: "app-sdk",
};
const initData = await postRobot.sendToParent<InitializationData>(
"init",
{ version, meta }
);
return initData.data;
}
setReady(): Promise<ResponseMessageEvent> {
return this.postRobot.sendToParent("ready");
}
}
export default Extension;
Source