@adobe/uix-guest 0.6.5-1 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/guest.ts","../src/debug-guest.ts","../src/guest-ui.ts","../src/guest-server.ts"],"sourcesContent":["/*\nCopyright 2022 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\n\n/**\n * @packageDocumentation\n * Tools for UI Extensions meant to run inside extensible apps. Connects\n * Extensions running in their own window contexts with the host app, allowing\n * the host and guest to exchange method, events, and signals.\n *\n * @remarks The core object of this library, which extensions use for\n * communication, is the Guest object. There are two variants of the Guest\n * object {@link GuestServer} for the bootstrap frame which your extension keeps\n * running in the background, and {@link GuestUI} for frames meant to be\n * displayed in the host application. An extension must have one GuestServer\n * frame, and the host app may choose to use one or more GuestUI frames.\n *\n * @example Creating and connecting a GuestServer with {@link register}\n * ```typescript\n * import { register } from \"@adobe/uix-guest\";\n *\n * const server = await register({\n * // Must match extension ID from registry\n * id: \"My Custom View Extension\",\n * // enable logging in dev build\n * debug: process.env.NODE_ENV !== \"production\",\n * // Host can access these methods from its Port to this guest\n * methods: {\n * // Methods must be namespaced by one or more levels\n * myCustomView: {\n * async documentIsViewable(docId) {\n * const doc = await callMyRuntimeAction(docId);\n * return someValidation(doc);\n * },\n * renderView(docId, depth) {\n * // Use a host method\n * const tooltip = await server.host.editor.requestTooltip({\n * type: 'frame',\n * url: new URL(`/show/${docId}`, location).href\n * })\n * }\n * },\n * },\n * })\n * ```\n *\n * @example Connecting to an existing GuestServer with a GuestUI\n * ```typescript\n * import { attach } from \"@adobe/uix-guest\";\n *\n * const ui = await attach({\n * id: \"My Custom View Extension\",\n * })\n *\n * // when editing is done:\n * const saved = await ui.host.editor.saveChanges();\n * if (!saved) {\n * const editorState = ui.sharedContext.get('editorState');\n * if (editorState.tooltips[ui.id].invalid === true) {\n * putGuestUIInInvalidState();\n * }\n * } else {\n * ui.host.editor.dismissTooltip();\n * }\n * ```\n *\n */\nimport type { Guest, GuestConfig } from \"./guest.js\";\nimport { GuestUI } from \"./guest-ui.js\";\nimport { GuestServer } from \"./guest-server.js\";\nimport { GuestApis } from \"@adobe/uix-core\";\n\n/**\n * {@inheritdoc GuestConfig}\n * @public\n */\ntype GuestConfigWithMethods<Outgoing extends GuestApis> = GuestConfig & {\n methods: Outgoing;\n};\n\n/**\n * Create and immediately return a {@link GuestServer}.\n *\n * @deprecated Use {@link attach} or {@link register}, which return Promises\n * that resolve once the guest is connected.\n * @public\n */\nexport function createGuest(config: GuestConfig) {\n const guest = new GuestServer(config);\n return guest;\n}\n\n/**\n * Connect to a running {@link GuestServer} to share its context and render UI.\n *\n * @remarks Creates a guest object that shares most of the GuestServer API,\n * except it cannot register its own methods. Use `attach()` in an app or\n * document that is meant to render a UI in the host application; it will have\n * access to the sharedContext object shared by the host and GuestServer.\n *\n * @public\n */\nexport async function attach(config: GuestConfig) {\n const guest = new GuestUI(config);\n await guest._connect();\n return guest;\n}\n\n/**\n * Initiate a connection to the host app and its extension points.\n *\n * @remarks Creates the \"main\" {@link GuestServer}, which runs in the background\n * without UI. Registers methods passed in the `methods` parameter, then\n * resolves the returned Promise with the connected GuestServer object.\n *\n * @public\n */\nexport async function register<Outgoing extends GuestApis>(\n config: GuestConfigWithMethods<Outgoing>\n) {\n const guest = new GuestServer(config);\n await guest.register(config.methods);\n return guest;\n}\n\n// backwards compatibility\nexport {\n Guest,\n Guest as BaseGuest,\n GuestUI,\n GuestUI as UIGuest,\n GuestServer,\n GuestServer as PrimaryGuest,\n};\n","/*\nCopyright 2022 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\n\n/* eslint @typescript-eslint/no-explicit-any: \"off\" */\nimport { Connection, connectToParent } from \"penpal\";\nimport type {\n RemoteHostApis,\n HostConnection,\n NamedEvent,\n VirtualApi,\n} from \"@adobe/uix-core\";\nimport {\n Emitter,\n makeNamespaceProxy,\n timeoutPromise,\n quietConsole,\n} from \"@adobe/uix-core\";\nimport { debugGuest } from \"./debug-guest.js\";\n\n/**\n * @public\n */\nexport type GuestEvent<\n Type extends string = string,\n Detail = Record<string, unknown>\n> = NamedEvent<\n Type,\n Detail &\n Record<string, unknown> & {\n guest: Guest;\n }\n>;\n\n/**\n * @public\n */\nexport type GuestEventContextChange = GuestEvent<\n \"contextchange\",\n { context: Record<string, unknown> }\n>;\n\n/** @public */\nexport type GuestEventBeforeConnect = GuestEvent<\"beforeconnect\">;\n/** @public */\nexport type GuestEventConnected = GuestEvent<\n \"connected\",\n { connection: Connection }\n>;\n/** @public */\nexport type GuestEventError = GuestEvent<\"error\", { error: Error }>;\n\n/**\n * @public\n */\nexport type GuestEvents =\n | GuestEventContextChange\n | GuestEventBeforeConnect\n | GuestEventConnected\n | GuestEventError;\n\n/**\n * @public\n */\nexport interface GuestConfig {\n /**\n * String slug identifying extension. This may need to use IDs from an\n * external system in the future.\n */\n id: string;\n /**\n * Set debug flags on all libraries that have them, and add loggers to SDK\n * objects. Log a lot to the console.\n */\n debug?: boolean;\n /**\n * Time out and stop trying to reach the host after this many milliseconds\n */\n timeout?: number;\n}\n\n/**\n * A `Map` representing the {@link @adobe/uix-host#HostConfig.sharedContext}\n * object.\n *\n * @remarks While the Host object is a plain JavaScript object. the `sharedContext` in the Guest object implements the {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map | Map} interface.\n *\n * @example\n * In the host app window, the Host object shares context:\n * ```javascript\n *host.shareContext({\n * someAuthToken: 'abc'\n *});\n * ```\n *\n * After the `contentchange` event has fired in the guest window:\n * ```javascript\n * guest.sharedContext.get('someAuthToken') === 'abc'\n * ```\n * @public\n */\nexport class SharedContext {\n private _map: Map<string, unknown>;\n constructor(values: Record<string, unknown>) {\n this.reset(values);\n }\n private reset(values: Record<string, unknown>) {\n this._map = new Map(Object.entries(values));\n }\n /**\n * @public\n * Retrieve a copy of a value from the {@link @adobe/uix-host#HostConfig.sharedContext} object. *Note that this is not a reference to any actual objects from the parent. If the parent updates an \"inner object\" inside the SharedContext, that change will not be reflected in the Guest!*\n */\n get(key: string) {\n return this._map.get(key);\n }\n}\n\n/**\n * Generic Guest object, with methods shared by all types of Guest.\n * @internal\n */\nexport class Guest<\n Incoming extends object = VirtualApi\n> extends Emitter<GuestEvents> {\n /**\n * Shared context has been set or updated.\n * @eventProperty\n */\n public contextchange: GuestEventContextChange;\n /**\n * About to attempt connection to the host.\n * @eventProperty\n */\n public beforeconnect: GuestEventBeforeConnect;\n /**\n * Host connection has been established.\n * @eventProperty\n */\n public connected: GuestEventConnected;\n /**\n * Host connection has failed.\n * @eventProperty\n */\n public error: GuestEventError;\n /**\n * {@inheritdoc SharedContext}\n */\n sharedContext: SharedContext;\n private debugLogger: Console = quietConsole;\n\n /**\n * @param config - Initializer for guest object, including ID.\n */\n constructor(config: GuestConfig) {\n super(config.id);\n if (typeof config.timeout === \"number\") {\n this.timeout = config.timeout;\n }\n if (config.debug) {\n this.debugLogger = debugGuest(this);\n }\n this.addEventListener(\"contextchange\", (event) => {\n this.sharedContext = new SharedContext(event.detail.context);\n });\n }\n /**\n * Proxy object for calling methods on the host.\n *\n * @remarks Any APIs exposed to the extension via {@link @adobe/uix-host#Port.provide}\n * can be called on this object. Because these methods are called with RPC,\n * they are all asynchronous, The return types of all Host methods will be\n * Promises which resolve to the value the Host method returns.\n * @public\n */\n host: RemoteHostApis<Incoming> = makeNamespaceProxy<Incoming>(\n async (address) => {\n await this.hostConnectionPromise;\n try {\n const result = await timeoutPromise(\n 10000,\n this.hostConnection.invokeHostMethod(address)\n );\n return result;\n } catch (e) {\n const error =\n e instanceof Error ? e : new Error(e as unknown as string);\n const methodError = new Error(\n `Host method call host.${address.path.join(\".\")}() failed: ${\n error.message\n }`\n );\n this.debugLogger.error(methodError);\n throw methodError;\n }\n }\n );\n private timeout = 10000;\n private hostConnectionPromise: Promise<RemoteHostApis<HostConnection>>;\n private hostConnection!: RemoteHostApis<HostConnection>;\n /** @internal */\n protected getLocalMethods() {\n return {\n emit: (...args: Parameters<typeof this.emit>) => {\n this.debugLogger.log(`Event \"${args[0]}\" emitted from host`);\n this.emit(...args);\n },\n };\n }\n /**\n * Accept a connection from the Host.\n * @returns A Promise that resolves when the Host has established a connection.\n * @deprecated It is preferable to use {@link register} for primary frames,\n * and {@link attach} for UI frames and other secondary frames, than to\n * instantiate a Guest and then call `.connect()` on it. The latter style\n * returns an object that cannot be used until it is connected, and therefore\n * risks errors.\n * @public\n */\n async connect() {\n return this._connect();\n }\n\n /**\n * @internal\n */\n async _connect() {\n this.emit(\"beforeconnect\", { guest: this });\n try {\n const connection = connectToParent<HostConnection<Incoming>>({\n timeout: this.timeout,\n methods: this.getLocalMethods(),\n });\n\n this.hostConnectionPromise = connection.promise;\n this.hostConnection = await this.hostConnectionPromise;\n this.sharedContext = new SharedContext(\n await this.hostConnection.getSharedContext()\n );\n this.debugLogger.log(\"retrieved sharedContext\", this.sharedContext);\n this.emit(\"connected\", { guest: this, connection });\n } catch (e) {\n this.emit(\"error\", { guest: this, error: e });\n this.debugLogger.error(\"Connection failed!\", e);\n }\n }\n}\n","/*\nCopyright 2022 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\n\n/**\n * Adapter to attach console logging listeners to a Guest running in a frame/\n * @internal @preapproved\n */\nimport { debugEmitter, Emits, EmitterDebugLogger } from \"@adobe/uix-core\";\nimport { GuestEvents } from \"./guest\";\n\nexport function debugGuest(guest: Emits<GuestEvents>): EmitterDebugLogger {\n return debugEmitter(guest, {\n theme: \"yellow medium\",\n type: \"Guest\",\n })\n .listen(\"beforeconnect\", (log, { detail: { guest } }) => {\n log.info(guest);\n })\n .listen(\"connecting\", (log, { detail: { connection } }) => {\n log.info(connection);\n })\n .listen(\"connected\", (log, { detail: { guest } }) => {\n log.info(guest);\n })\n .listen(\"error\", (log, { detail: { error, guest } }) => {\n log.error(\n \"❌ Failed to connect! %s\",\n (error as Error).message,\n guest,\n error\n );\n });\n}\n","/*\nCopyright 2022 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\n\nimport type { RemoteHostApis, VirtualApi } from \"@adobe/uix-core\";\nimport {\n Guest,\n GuestConfig,\n GuestEventBeforeConnect,\n GuestEventConnected,\n GuestEventContextChange,\n GuestEventError,\n} from \"./guest\";\n\n/**\n * A Guest to be used in an extension-controlled frame, usually to display UI.\n *\n * @typeParam Incoming - Optional interface of host methods. If using\n * TypeScript, supply this type parameter and a promisified version of the\n * interface will be available at {@link Guest.host}\n *\n * @remarks\n * This is the object returned when calling {@link @adobe/uix-guest#attach}. It\n * represents an additional frame or runtime created by the host application, on\n * behalf of the extension's control frame which is running the {@link\n * GuestServer}. It is a \"secondary\" guest object, which a host won't use before\n * the control frame has connected. It exposes a subset of the functionality of\n * the {@link GuestServer}.\n *\n * Unlike the {@link GuestServer}, it cannot register methods or update the\n * {@link Guest.sharedContext}, but it remains in sync with the GuestServer and\n * can access the {@link Guest.sharedContext} of the control frame, as well as\n * any of the published methods on the host.\n *\n * Extensible host apps using the React bindings will likely render GuestUI\n * frames using the {@link @adobe/uix-host-react#GuestUIFrame} component.\n *\n * @example\n * When an extensible app renders this page, {@link @adobe/uix-guest#attach}\n * creates a GuestUI. Once it attaches to the host, it\n * ```javascript\n * import React, { useEffect, useState } from \"react\";\n * import { attach } from \"@adobe/uix-guest\";\n * import { Tooltip } from \"./tooltip\";\n *\n * export default function PopupOverlay(props) {\n * // how large am I?\n * const [dimensions, setDimensions] = useState(\n * document.body.getBoundingClientRect()\n * );\n * // if possible, use language preloaded in query parameters\n * const [language, setLanguage] = useState(props.params.lang)\n *\n * // attach only once, in a useEffect\n * useEffect(() => {\n * attach({\n * id: \"my-extension-id\",\n * debug: true,\n * })\n * .then(guestUI => {\n * // this event fires whenever the host, or the control frame, changes\n * // any sharedContext value\n * guestUI.addEventListener(\"contextchange\", ({ detail: { context }}) => {\n * setLanguage(context.lang)\n * });\n * // how large does the host want me to be?\n * return guestUI.host.tooltips.getDimensions()\n * .then(setDimensions)\n * })\n * .catch((e) => {\n * console.error(\"ui attach failed\", e);\n * });\n * }, []);\n * // render UI! Due to the setup and useState, this component will re-render\n * // once attach() is complete.\n * return (\n * <Tooltip {...props.params} lang={language} dimensions={dimensions} />\n * );\n * }\n * ```\n *\n * @public\n */\nexport class GuestUI<IHost extends VirtualApi> extends Guest<IHost> {\n /**\n * {@inheritDoc Guest.\"constructor\"}\n */\n constructor(config: GuestConfig) {\n super(config);\n }\n /**\n * {@inheritDoc Guest.contextchange}\n * @eventProperty\n */\n public contextchange: GuestEventContextChange;\n /**\n * {@inheritDoc Guest.beforeconnect}\n * @eventProperty\n */\n public beforeconnect: GuestEventBeforeConnect;\n /**\n * {@inheritDoc Guest.connected}\n * @eventProperty\n */\n public connected: GuestEventConnected;\n /**\n * {@inheritDoc Guest.error}\n * @eventProperty\n */\n public error: GuestEventError;\n /**\n * {@inheritDoc Guest.host}\n */\n host: RemoteHostApis<IHost>;\n}\n","/*\nCopyright 2022 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\n\nimport type { GuestApis } from \"@adobe/uix-core\";\nimport type { SharedContext } from \"./guest\";\nimport { Guest } from \"./guest\";\n\n/**\n * A Guest to be used in the \"main\" or primary frame of an extension, the frame\n * the Host loads first.\n *\n * @remarks This is the Guest object returned from {@link register}. It can\n * expose internal methods to the Host via the {@link GuestServer.register}\n * method.\n *\n *\n * @public\n */\nexport class GuestServer<Outgoing extends GuestApis> extends Guest<Outgoing> {\n private localMethods: Outgoing;\n protected getLocalMethods() {\n return {\n ...super.getLocalMethods(),\n apis: this.localMethods,\n };\n }\n /**\n * {@inheritDoc BaseGuest.sharedContext}\n */\n sharedContext: SharedContext;\n /**\n * {@inheritdoc BaseGuest.host}\n */\n host: Guest<Outgoing>[\"host\"];\n /**\n * Pass an interface of methods which Host may call as callbacks.\n *\n * @remarks It is preferable to use {@link register} to obtain a guest object\n * and register local methods in one step. The returned guest object will be\n * pre-registered and connected.\n * @public\n */\n async register(implementedMethods: Outgoing) {\n this.localMethods = implementedMethods;\n return this._connect();\n }\n}\n"],"mappings":"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","names":["import_uix_core","guest","Guest","Guest","Guest"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/guest.ts","../src/debug-guest.ts","../src/guest-ui.ts","../src/guest-server.ts"],"sourcesContent":["/*\nCopyright 2022 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\n\n/**\n * @packageDocumentation\n * Tools for UI Extensions meant to run inside extensible apps. Connects\n * Extensions running in their own window contexts with the host app, allowing\n * the host and guest to exchange method, events, and signals.\n *\n * @remarks The core object of this library, which extensions use for\n * communication, is the Guest object. There are two variants of the Guest\n * object {@link GuestServer} for the bootstrap frame which your extension keeps\n * running in the background, and {@link GuestUI} for frames meant to be\n * displayed in the host application. An extension must have one GuestServer\n * frame, and the host app may choose to use one or more GuestUI frames.\n *\n * @example Creating and connecting a GuestServer with {@link register}\n * ```typescript\n * import { register } from \"@adobe/uix-guest\";\n *\n * const server = await register({\n * // Must match extension ID from registry\n * id: \"My Custom View Extension\",\n * // enable logging in dev build\n * debug: process.env.NODE_ENV !== \"production\",\n * // Host can access these methods from its Port to this guest\n * methods: {\n * // Methods must be namespaced by one or more levels\n * myCustomView: {\n * async documentIsViewable(docId) {\n * const doc = await callMyRuntimeAction(docId);\n * return someValidation(doc);\n * },\n * renderView(docId, depth) {\n * // Use a host method\n * const tooltip = await server.host.editor.requestTooltip({\n * type: 'frame',\n * url: new URL(`/show/${docId}`, location).href\n * })\n * }\n * },\n * },\n * })\n * ```\n *\n * @example Connecting to an existing GuestServer with a GuestUI\n * ```typescript\n * import { attach } from \"@adobe/uix-guest\";\n *\n * const ui = await attach({\n * id: \"My Custom View Extension\",\n * })\n *\n * // when editing is done:\n * const saved = await ui.host.editor.saveChanges();\n * if (!saved) {\n * const editorState = ui.sharedContext.get('editorState');\n * if (editorState.tooltips[ui.id].invalid === true) {\n * putGuestUIInInvalidState();\n * }\n * } else {\n * ui.host.editor.dismissTooltip();\n * }\n * ```\n *\n */\nimport type { Guest, GuestConfig } from \"./guest.js\";\nimport { GuestUI } from \"./guest-ui.js\";\nimport { GuestServer } from \"./guest-server.js\";\nimport { GuestApis } from \"@adobe/uix-core\";\n\n/**\n * {@inheritdoc GuestConfig}\n * @public\n */\ntype GuestConfigWithMethods<Outgoing extends GuestApis> = GuestConfig & {\n methods: Outgoing;\n};\n\n/**\n * Create and immediately return a {@link GuestServer}.\n *\n * @deprecated Use {@link attach} or {@link register}, which return Promises\n * that resolve once the guest is connected.\n * @public\n */\nexport function createGuest(config: GuestConfig) {\n const guest = new GuestServer(config);\n return guest;\n}\n\n/**\n * Connect to a running {@link GuestServer} to share its context and render UI.\n *\n * @remarks Creates a guest object that shares most of the GuestServer API,\n * except it cannot register its own methods. Use `attach()` in an app or\n * document that is meant to render a UI in the host application; it will have\n * access to the sharedContext object shared by the host and GuestServer.\n *\n * @public\n */\nexport async function attach(config: GuestConfig) {\n const guest = new GuestUI(config);\n await guest._connect();\n return guest;\n}\n\n/**\n * Initiate a connection to the host app and its extension points.\n *\n * @remarks Creates the \"main\" {@link GuestServer}, which runs in the background\n * without UI. Registers methods passed in the `methods` parameter, then\n * resolves the returned Promise with the connected GuestServer object.\n *\n * @public\n */\nexport async function register<Outgoing extends GuestApis>(\n config: GuestConfigWithMethods<Outgoing>\n) {\n const guest = new GuestServer(config);\n await guest.register(config.methods);\n return guest;\n}\n\n// backwards compatibility\nexport {\n Guest,\n Guest as BaseGuest,\n GuestUI,\n GuestUI as UIGuest,\n GuestServer,\n GuestServer as PrimaryGuest,\n};\n","/*\nCopyright 2022 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\n\n/* eslint @typescript-eslint/no-explicit-any: \"off\" */\nimport type {\n RemoteHostApis,\n HostConnection,\n NamedEvent,\n CrossRealmObject,\n VirtualApi,\n} from \"@adobe/uix-core\";\nimport {\n Emitter,\n makeNamespaceProxy,\n connectParentWindow,\n timeoutPromise,\n quietConsole,\n} from \"@adobe/uix-core\";\nimport { debugGuest } from \"./debug-guest.js\";\n\n/**\n * @public\n */\nexport type GuestEvent<\n Type extends string = string,\n Detail = Record<string, unknown>\n> = NamedEvent<\n Type,\n Detail &\n Record<string, unknown> & {\n guest: Guest;\n }\n>;\n\n/**\n * @public\n */\nexport type GuestEventContextChange = GuestEvent<\n \"contextchange\",\n { context: Record<string, unknown> }\n>;\n\n/** @public */\nexport type GuestEventBeforeConnect = GuestEvent<\"beforeconnect\">;\n/** @public */\nexport type GuestEventConnected = GuestEvent<\"connected\">;\n/** @public */\nexport type GuestEventError = GuestEvent<\"error\", { error: Error }>;\n\n/**\n * @public\n */\nexport type GuestEvents =\n | GuestEventContextChange\n | GuestEventBeforeConnect\n | GuestEventConnected\n | GuestEventError;\n\n/**\n * @public\n */\nexport interface GuestConfig {\n /**\n * String slug identifying extension. This may need to use IDs from an\n * external system in the future.\n */\n id: string;\n /**\n * Set debug flags on all libraries that have them, and add loggers to SDK\n * objects. Log a lot to the console.\n */\n debug?: boolean;\n /**\n * Time out and stop trying to reach the host after this many milliseconds\n */\n timeout?: number;\n}\n\n/**\n * A `Map` representing the {@link @adobe/uix-host#HostConfig.sharedContext}\n * object.\n *\n * @remarks While the Host object is a plain JavaScript object. the `sharedContext` in the Guest object implements the {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map | Map} interface.\n *\n * @example\n * In the host app window, the Host object shares context:\n * ```javascript\n *host.shareContext({\n * someAuthToken: 'abc'\n *});\n * ```\n *\n * After the `contentchange` event has fired in the guest window:\n * ```javascript\n * guest.sharedContext.get('someAuthToken') === 'abc'\n * ```\n * @public\n */\nexport class SharedContext {\n private _map: Map<string, unknown>;\n constructor(values: Record<string, unknown>) {\n this.reset(values);\n }\n private reset(values: Record<string, unknown>) {\n this._map = new Map(Object.entries(values));\n }\n /**\n * @public\n * Retrieve a copy of a value from the {@link @adobe/uix-host#HostConfig.sharedContext} object. *Note that this is not a reference to any actual objects from the parent. If the parent updates an \"inner object\" inside the SharedContext, that change will not be reflected in the Guest!*\n */\n get(key: string) {\n return this._map.get(key);\n }\n}\n\n/**\n * Generic Guest object, with methods shared by all types of Guest.\n * @internal\n */\nexport class Guest<\n Incoming extends object = VirtualApi\n> extends Emitter<GuestEvents> {\n /**\n * Shared context has been set or updated.\n * @eventProperty\n */\n public contextchange: GuestEventContextChange;\n /**\n * About to attempt connection to the host.\n * @eventProperty\n */\n public beforeconnect: GuestEventBeforeConnect;\n /**\n * Host connection has been established.\n * @eventProperty\n */\n public connected: GuestEventConnected;\n /**\n * Host connection has failed.\n * @eventProperty\n */\n public error: GuestEventError;\n /**\n * {@inheritdoc SharedContext}\n */\n sharedContext: SharedContext;\n logger: Console = quietConsole;\n\n /**\n * @param config - Initializer for guest object, including ID.\n */\n constructor(config: GuestConfig) {\n super(config.id);\n if (typeof config.timeout === \"number\") {\n this.timeout = config.timeout;\n }\n if (config.debug) {\n this.logger = debugGuest(this);\n }\n this.addEventListener(\"contextchange\", (event) => {\n this.sharedContext = new SharedContext(event.detail.context);\n });\n }\n /**\n * Proxy object for calling methods on the host.\n *\n * @remarks Any APIs exposed to the extension via {@link @adobe/uix-host#Port.provide}\n * can be called on this object. Because these methods are called with RPC,\n * they are all asynchronous, The return types of all Host methods will be\n * Promises which resolve to the value the Host method returns.\n * @public\n */\n host: RemoteHostApis<Incoming> = makeNamespaceProxy<Incoming>(\n async (address) => {\n await this.hostConnectionPromise;\n try {\n const result = await timeoutPromise(\n `Calling host method ${address.path.join(\".\")}${address.name}(...)`,\n this.hostConnection.getRemoteApi().invokeHostMethod(address),\n 10000,\n (e) => {\n this.logger.error(e);\n }\n );\n return result;\n } catch (e) {\n const error =\n e instanceof Error ? e : new Error(e as unknown as string);\n const methodError = new Error(\n `Host method call host.${address.path.join(\".\")}() failed: ${\n error.message\n }`\n );\n this.logger.error(methodError);\n throw methodError;\n }\n }\n );\n private timeout = 10000;\n private hostConnectionPromise: Promise<CrossRealmObject<HostConnection>>;\n private hostConnection!: CrossRealmObject<HostConnection>;\n /** @internal */\n protected getLocalMethods() {\n return {\n emit: (...args: Parameters<typeof this.emit>) => {\n this.logger.log(`Event \"${args[0]}\" emitted from host`);\n this.emit(...args);\n },\n };\n }\n /**\n * Accept a connection from the Host.\n * @returns A Promise that resolves when the Host has established a connection.\n * @deprecated It is preferable to use {@link register} for primary frames,\n * and {@link attach} for UI frames and other secondary frames, than to\n * instantiate a Guest and then call `.connect()` on it. The latter style\n * returns an object that cannot be used until it is connected, and therefore\n * risks errors.\n * @public\n */\n async connect() {\n return this._connect();\n }\n\n /**\n * @internal\n */\n async _connect() {\n this.emit(\"beforeconnect\", { guest: this });\n try {\n const hostConnectionPromise = connectParentWindow<HostConnection>(\n {\n targetOrigin: \"*\",\n timeout: this.timeout,\n },\n this.getLocalMethods()\n );\n\n this.hostConnectionPromise = hostConnectionPromise;\n this.hostConnection = await this.hostConnectionPromise;\n } catch (e) {\n this.emit(\"error\", { guest: this, error: e });\n this.logger.error(\"Connection failed!\", e);\n return;\n }\n try {\n this.sharedContext = new SharedContext(\n await this.hostConnection.getRemoteApi().getSharedContext()\n );\n } catch (e) {\n this.emit(\"error\", { guest: this, error: e });\n this.logger.error(\"getSharedContext failed!\", e);\n }\n }\n}\n","/*\nCopyright 2022 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\n\n/**\n * Adapter to attach console logging listeners to a Guest running in a frame/\n * @internal @preapproved\n */\nimport { debugEmitter, Emits, EmitterDebugLogger } from \"@adobe/uix-core\";\nimport { GuestEvents } from \"./guest\";\n\nexport function debugGuest(guest: Emits<GuestEvents>): EmitterDebugLogger {\n return debugEmitter(guest, {\n theme: \"yellow medium\",\n type: \"Guest\",\n })\n .listen(\"beforeconnect\", (log, { detail: { guest } }) => {\n log.info(guest);\n })\n .listen(\"connecting\", (log, { detail: { connection } }) => {\n log.info(connection);\n })\n .listen(\"connected\", (log, { detail: { guest } }) => {\n log.info(guest);\n })\n .listen(\"error\", (log, { detail: { error, guest } }) => {\n log.error(\n \"❌ Failed to connect! %s\",\n (error as Error).message,\n guest,\n error\n );\n });\n}\n","/*\nCopyright 2022 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\n\nimport type { RemoteHostApis, VirtualApi } from \"@adobe/uix-core\";\nimport {\n Guest,\n GuestConfig,\n GuestEventBeforeConnect,\n GuestEventConnected,\n GuestEventContextChange,\n GuestEventError,\n} from \"./guest\";\n\n/**\n * A Guest to be used in an extension-controlled frame, usually to display UI.\n *\n * @typeParam Incoming - Optional interface of host methods. If using\n * TypeScript, supply this type parameter and a promisified version of the\n * interface will be available at {@link Guest.host}\n *\n * @remarks\n * This is the object returned when calling {@link @adobe/uix-guest#attach}. It\n * represents an additional frame or runtime created by the host application, on\n * behalf of the extension's control frame which is running the {@link\n * GuestServer}. It is a \"secondary\" guest object, which a host won't use before\n * the control frame has connected. It exposes a subset of the functionality of\n * the {@link GuestServer}.\n *\n * Unlike the {@link GuestServer}, it cannot register methods or update the\n * {@link Guest.sharedContext}, but it remains in sync with the GuestServer and\n * can access the {@link Guest.sharedContext} of the control frame, as well as\n * any of the published methods on the host.\n *\n * Extensible host apps using the React bindings will likely render GuestUI\n * frames using the {@link @adobe/uix-host-react#GuestUIFrame} component.\n *\n * @example\n * When an extensible app renders this page, {@link @adobe/uix-guest#attach}\n * creates a GuestUI. Once it attaches to the host, it\n * ```javascript\n * import React, { useEffect, useState } from \"react\";\n * import { attach } from \"@adobe/uix-guest\";\n * import { Tooltip } from \"./tooltip\";\n *\n * export default function PopupOverlay(props) {\n * // how large am I?\n * const [dimensions, setDimensions] = useState(\n * document.body.getBoundingClientRect()\n * );\n * // if possible, use language preloaded in query parameters\n * const [language, setLanguage] = useState(props.params.lang)\n *\n * // attach only once, in a useEffect\n * useEffect(() => {\n * attach({\n * id: \"my-extension-id\",\n * debug: true,\n * })\n * .then(guestUI => {\n * // this event fires whenever the host, or the control frame, changes\n * // any sharedContext value\n * guestUI.addEventListener(\"contextchange\", ({ detail: { context }}) => {\n * setLanguage(context.lang)\n * });\n * // how large does the host want me to be?\n * return guestUI.host.tooltips.getDimensions()\n * .then(setDimensions)\n * })\n * .catch((e) => {\n * console.error(\"ui attach failed\", e);\n * });\n * }, []);\n * // render UI! Due to the setup and useState, this component will re-render\n * // once attach() is complete.\n * return (\n * <Tooltip {...props.params} lang={language} dimensions={dimensions} />\n * );\n * }\n * ```\n *\n * @public\n */\nexport class GuestUI<IHost extends VirtualApi> extends Guest<IHost> {\n /**\n * {@inheritDoc Guest.\"constructor\"}\n */\n constructor(config: GuestConfig) {\n super(config);\n }\n /**\n * {@inheritDoc Guest.contextchange}\n * @eventProperty\n */\n public contextchange: GuestEventContextChange;\n /**\n * {@inheritDoc Guest.beforeconnect}\n * @eventProperty\n */\n public beforeconnect: GuestEventBeforeConnect;\n /**\n * {@inheritDoc Guest.connected}\n * @eventProperty\n */\n public connected: GuestEventConnected;\n /**\n * {@inheritDoc Guest.error}\n * @eventProperty\n */\n public error: GuestEventError;\n /**\n * {@inheritDoc Guest.host}\n */\n host: RemoteHostApis<IHost>;\n}\n","/*\nCopyright 2022 Adobe. All rights reserved.\nThis file is licensed to you under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License. You may obtain a copy\nof the License at http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software distributed under\nthe License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\nOF ANY KIND, either express or implied. See the License for the specific language\ngoverning permissions and limitations under the License.\n*/\n\nimport type { GuestApis } from \"@adobe/uix-core\";\nimport type { SharedContext } from \"./guest\";\nimport { Guest } from \"./guest\";\n\n/**\n * A Guest to be used in the \"main\" or primary frame of an extension, the frame\n * the Host loads first.\n *\n * @remarks This is the Guest object returned from {@link register}. It can\n * expose internal methods to the Host via the {@link GuestServer.register}\n * method.\n *\n *\n * @public\n */\nexport class GuestServer<Outgoing extends GuestApis> extends Guest<Outgoing> {\n private localMethods: Outgoing;\n protected getLocalMethods() {\n return {\n ...super.getLocalMethods(),\n apis: this.localMethods,\n };\n }\n /**\n * {@inheritDoc BaseGuest.sharedContext}\n */\n sharedContext: SharedContext;\n /**\n * {@inheritdoc BaseGuest.host}\n */\n host: Guest<Outgoing>[\"host\"];\n /**\n * Pass an interface of methods which Host may call as callbacks.\n *\n * @remarks It is preferable to use {@link register} to obtain a guest object\n * and register local methods in one step. The returned guest object will be\n * pre-registered and connected.\n * @public\n */\n async register(implementedMethods: Outgoing) {\n this.localMethods = implementedMethods;\n return this._connect();\n }\n}\n"],"mappings":"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","names":["import_uix_core","guest","Guest","Guest","Guest"]}
package/package.json CHANGED
@@ -1,6 +1,9 @@
1
1
  {
2
2
  "name": "@adobe/uix-guest",
3
- "version": "0.6.5-1",
3
+ "version": "0.7.0",
4
+ "publishConfig": {
5
+ "access": "public"
6
+ },
4
7
  "description": "Tools for connecting to UIX Host apps from extension apps",
5
8
  "author": "Adobe, Inc,",
6
9
  "main": "dist/index.js",
@@ -15,8 +18,7 @@
15
18
  ],
16
19
  "bugs": "https://github.com/adobe/uix-sdk/issues",
17
20
  "dependencies": {
18
- "@adobe/uix-core": "^0.6.5-1",
19
- "penpal": "~6.2.2"
21
+ "@adobe/uix-core": "^0.7.0"
20
22
  },
21
23
  "files": [
22
24
  "README.md",
package/src/guest.ts CHANGED
@@ -11,16 +11,17 @@ governing permissions and limitations under the License.
11
11
  */
12
12
 
13
13
  /* eslint @typescript-eslint/no-explicit-any: "off" */
14
- import { Connection, connectToParent } from "penpal";
15
14
  import type {
16
15
  RemoteHostApis,
17
16
  HostConnection,
18
17
  NamedEvent,
18
+ CrossRealmObject,
19
19
  VirtualApi,
20
20
  } from "@adobe/uix-core";
21
21
  import {
22
22
  Emitter,
23
23
  makeNamespaceProxy,
24
+ connectParentWindow,
24
25
  timeoutPromise,
25
26
  quietConsole,
26
27
  } from "@adobe/uix-core";
@@ -51,10 +52,7 @@ export type GuestEventContextChange = GuestEvent<
51
52
  /** @public */
52
53
  export type GuestEventBeforeConnect = GuestEvent<"beforeconnect">;
53
54
  /** @public */
54
- export type GuestEventConnected = GuestEvent<
55
- "connected",
56
- { connection: Connection }
57
- >;
55
+ export type GuestEventConnected = GuestEvent<"connected">;
58
56
  /** @public */
59
57
  export type GuestEventError = GuestEvent<"error", { error: Error }>;
60
58
 
@@ -155,7 +153,7 @@ export class Guest<
155
153
  * {@inheritdoc SharedContext}
156
154
  */
157
155
  sharedContext: SharedContext;
158
- private debugLogger: Console = quietConsole;
156
+ logger: Console = quietConsole;
159
157
 
160
158
  /**
161
159
  * @param config - Initializer for guest object, including ID.
@@ -166,7 +164,7 @@ export class Guest<
166
164
  this.timeout = config.timeout;
167
165
  }
168
166
  if (config.debug) {
169
- this.debugLogger = debugGuest(this);
167
+ this.logger = debugGuest(this);
170
168
  }
171
169
  this.addEventListener("contextchange", (event) => {
172
170
  this.sharedContext = new SharedContext(event.detail.context);
@@ -186,8 +184,12 @@ export class Guest<
186
184
  await this.hostConnectionPromise;
187
185
  try {
188
186
  const result = await timeoutPromise(
187
+ `Calling host method ${address.path.join(".")}${address.name}(...)`,
188
+ this.hostConnection.getRemoteApi().invokeHostMethod(address),
189
189
  10000,
190
- this.hostConnection.invokeHostMethod(address)
190
+ (e) => {
191
+ this.logger.error(e);
192
+ }
191
193
  );
192
194
  return result;
193
195
  } catch (e) {
@@ -198,19 +200,19 @@ export class Guest<
198
200
  error.message
199
201
  }`
200
202
  );
201
- this.debugLogger.error(methodError);
203
+ this.logger.error(methodError);
202
204
  throw methodError;
203
205
  }
204
206
  }
205
207
  );
206
208
  private timeout = 10000;
207
- private hostConnectionPromise: Promise<RemoteHostApis<HostConnection>>;
208
- private hostConnection!: RemoteHostApis<HostConnection>;
209
+ private hostConnectionPromise: Promise<CrossRealmObject<HostConnection>>;
210
+ private hostConnection!: CrossRealmObject<HostConnection>;
209
211
  /** @internal */
210
212
  protected getLocalMethods() {
211
213
  return {
212
214
  emit: (...args: Parameters<typeof this.emit>) => {
213
- this.debugLogger.log(`Event "${args[0]}" emitted from host`);
215
+ this.logger.log(`Event "${args[0]}" emitted from host`);
214
216
  this.emit(...args);
215
217
  },
216
218
  };
@@ -235,21 +237,28 @@ export class Guest<
235
237
  async _connect() {
236
238
  this.emit("beforeconnect", { guest: this });
237
239
  try {
238
- const connection = connectToParent<HostConnection<Incoming>>({
239
- timeout: this.timeout,
240
- methods: this.getLocalMethods(),
241
- });
240
+ const hostConnectionPromise = connectParentWindow<HostConnection>(
241
+ {
242
+ targetOrigin: "*",
243
+ timeout: this.timeout,
244
+ },
245
+ this.getLocalMethods()
246
+ );
242
247
 
243
- this.hostConnectionPromise = connection.promise;
248
+ this.hostConnectionPromise = hostConnectionPromise;
244
249
  this.hostConnection = await this.hostConnectionPromise;
250
+ } catch (e) {
251
+ this.emit("error", { guest: this, error: e });
252
+ this.logger.error("Connection failed!", e);
253
+ return;
254
+ }
255
+ try {
245
256
  this.sharedContext = new SharedContext(
246
- await this.hostConnection.getSharedContext()
257
+ await this.hostConnection.getRemoteApi().getSharedContext()
247
258
  );
248
- this.debugLogger.log("retrieved sharedContext", this.sharedContext);
249
- this.emit("connected", { guest: this, connection });
250
259
  } catch (e) {
251
260
  this.emit("error", { guest: this, error: e });
252
- this.debugLogger.error("Connection failed!", e);
261
+ this.logger.error("getSharedContext failed!", e);
253
262
  }
254
263
  }
255
264
  }