UNPKG

forma-embedded-view-sdk

Version:

The Forma Embedded View SDK is a JavaScript library for creating custom extensions in Autodesk Forma (previously Spacemaker).

180 lines (179 loc) 6.71 kB
import type { EventHandler, RequestHandler, SubscribeHandler } from "./types.js"; /** * Structured error that can be used for errors on requests, * such as data validation errors. * * A handler can throw this error and it will properly be serialized * as part of the reply and deserialized on the other side. This allows * to return errors with additional context as a low-level primitive. */ export declare class RequestError extends Error { type: string; data: unknown; constructor(message: string, type: string, data: unknown, options?: { cause?: unknown; }); } declare const messageTypeRequest = "IFRAME-MESSAGE-REQUEST"; declare const messageTypeResponse = "IFRAME-MESSAGE-RESPONSE"; declare const messageTypeEvent = "IFRAME-MESSAGE-EVENT"; /** * @hidden * @internal */ export type IframeMessageEvent = { type: typeof messageTypeEvent; action: string; payload: unknown; }; /** * @hidden * @internal */ export type IframeMessageRequest = { /** * The ID is a unique identifier used to connect * the response message to the proper request. */ id: string; type: typeof messageTypeRequest; action: string; payload: unknown; }; /** * @hidden * @internal */ export type IframeMessageResponse = { /** * The ID is a unique identifier used to connect * the response message to the proper request. */ id: string; type: typeof messageTypeResponse; payload: unknown; error?: boolean | undefined; }; /** * @hidden * @internal */ export type CreateSubscriptionResult = { unsubscribe: () => void; }; /** * @hidden * @internal */ export type IframeMessengerOptions = { source: Window; /** * The origin where messages are expected from and that we will * use as destination for outgoing messages. * * Set to undefined if not checking origin in incoming messages * and sending outgoing messages to "*". * * Do not use undefined in the configuration side of an iframe if * sending sensitive data such as credentials. */ sourceOrigin?: string | undefined; requestResolver?: ((action: string) => RequestHandler | undefined) | undefined; eventResolver?: ((action: string) => EventHandler | undefined) | undefined; subscribeResolver?: ((name: string) => SubscribeHandler | undefined) | undefined; debug?: boolean | undefined; /** * A function that optionally returns a function that can be used to * intercept incoming postMessage messages, before they are passed * to the relevant handlers. This can be used to transform the incoming data. */ incomingMessageInterceptorResolver?: (() => ((message: unknown) => unknown) | undefined) | undefined; /** * A function that optionally returns a function that can be used to * intercept outgoing postMessage messages, before they are sent using * postMessage. This can be used to transform the outgoing data. */ outgoingMessageInterceptorResolver?: (() => ((message: unknown, options: { request?: IframeMessageRequest | undefined; }) => unknown) | undefined) | undefined; }; type DeregisterFn = () => void; /** * IframeMessenger handles communication in/out of an iframe. * * It creates an abstraction on top of the Window.postMessage() browser * API to make it more convenient to handle states, message passing * and routing messages to handlers. * * Functionality provided: * * - Sending requests and waiting for the response for it. Think of it * as a way of doing async functions across browser windows. Since the * cross-window communcation is async itself, there is no support for * synchronous requests. * * - Sending events to the other window. Events are one-way messages that * do not expect a reply. Use cases for this is rare, and in most * cases solved by subscriptions instead. * * - Subscriptions. This is a way to subscribe to specific events from the * other window. The window that exposes a subscription source will contain * a handler that can emit events for it when the subscription is created. * This allows for lazy event streams that are only created when needed. * * Internally subscriptions are built on top of both requests (creating and * deleting subscriptions) and events mentioned above. * * Subscriptions are unsubscribed automatically on disconnect. * * - Connected callbacks. This allows to add logic that should happen * as soon as the connection between the windows are established. * * By default messages are queued until the connection is established, * so the user does not have to be concerned about connection details. * * When an iframe is removed from DOM, the connection should be explicitly * disconnected by calling disconnect() to trigger proper cleanup. * * @hidden * @internal */ export declare class IframeMessenger { #private; debug: boolean; source: Window; sourceOrigin: string | undefined; incomingMessageInterceptorResolver: (() => ((message: unknown) => unknown) | undefined) | undefined; outgoingMessageInterceptorResolver: (() => ((message: unknown, options: { request?: IframeMessageRequest | undefined; }) => unknown) | undefined) | undefined; requestResolver: ((action: string) => RequestHandler | undefined) | undefined; eventResolver: ((action: string) => EventHandler | undefined) | undefined; subscribeResolver: ((name: string) => SubscribeHandler | undefined) | undefined; constructor(options: IframeMessengerOptions); connect(): void; disconnect(): void; /** * Subscribe to state transitions for being connected and * from being connected to disconnected. * * This essentially acts as a boolean flag if it is connected * or not. */ onStateChange(handler: (state: "connected" | "disconnected") => void): DeregisterFn; get isConnected(): boolean; /** * Wait for the state to be connected. * * If a disconnect (e.g. due to unmount) is requested before being * connected, the promise will be rejected to ensure the promise * is fulfilled. */ connectedPromise(): Promise<void>; sendRequest<R>(action: string): Promise<R>; sendRequest<T, R>(action: string, payload: T, transfer?: Transferable[]): Promise<R>; sendEvent(action: string): Promise<void>; sendEvent<T>(action: string, payload: T, transfer?: Transferable[]): Promise<void>; createSubscription<T, O extends Record<string, unknown> = Record<string, unknown>>(name: string, handler: (event: T) => void, options?: O): Promise<CreateSubscriptionResult>; } export {};