For those who wish to play with the History API in Forge apps, please note that the @forge/bridge view.createHistory() typings are misleading.
According to the typings, the createHistory() method will return a vanilla History object:
createHistory: () => Promise<import("history").History>;
That import leads to the following package, as defined in package.json:
"@types/history": "^4.7.11",
As per the definition of history in that package, it is defined as:
export interface History<HistoryLocationState = LocationState> {
length: number;
action: Action;
location: Location<HistoryLocationState>;
push(location: Path | LocationDescriptor<HistoryLocationState>, state?: HistoryLocationState): void;
replace(location: Path | LocationDescriptor<HistoryLocationState>, state?: HistoryLocationState): void;
go(n: number): void;
goBack(): void;
goForward(): void;
block(prompt?: boolean | string | TransitionPromptHook<HistoryLocationState>): UnregisterCallback;
listen(listener: LocationListener<HistoryLocationState>): UnregisterCallback;
createHref(location: LocationDescriptorObject<HistoryLocationState>): Href;
}
However, the actual implementation of @forge/bridge does not follow this specification, specifically for createHref(location: LocationDescriptorObject<HistoryLocationState>): Href.
When calling createHref() on the History object created by @forge/bridge, the method returns a Promise.
This is probably due to the fact that the implementation is based on messaging between parent window and Forge iframe, but the fact remains that this means that manipulating History is not a synchronous operation in Forge. And that has ramifications for apps that rely on it.
So Atlassian, either please change the History operations to be synchronous, or adjust the bindings and make sure that you are not pretending to follow the official History object typings when you’re not.