@adobe/uix-guest 0.6.5 → 0.7.1-nightly.20230114
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/guest-server.d.ts +0 -4
- package/dist/guest-server.d.ts.map +1 -1
- package/dist/guest.d.ts +2 -9
- package/dist/guest.d.ts.map +1 -1
- package/dist/iife/index.js +898 -362
- package/dist/iife/index.js.map +1 -1
- package/dist/index.js +26 -15
- package/dist/index.js.map +1 -1
- package/package.json +2 -3
- package/src/guest.ts +31 -21
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 logger: this.logger,\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,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@adobe/uix-guest",
|
3
|
-
"version": "0.
|
3
|
+
"version": "0.7.1-nightly.20230114",
|
4
4
|
"publishConfig": {
|
5
5
|
"access": "public"
|
6
6
|
},
|
@@ -18,8 +18,7 @@
|
|
18
18
|
],
|
19
19
|
"bugs": "https://github.com/adobe/uix-sdk/issues",
|
20
20
|
"dependencies": {
|
21
|
-
"@adobe/uix-core": "^0.
|
22
|
-
"penpal": "~6.2.2"
|
21
|
+
"@adobe/uix-core": "^0.7.1-nightly.20230114"
|
23
22
|
},
|
24
23
|
"files": [
|
25
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
|
-
|
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.
|
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
|
-
|
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.
|
203
|
+
this.logger.error(methodError);
|
202
204
|
throw methodError;
|
203
205
|
}
|
204
206
|
}
|
205
207
|
);
|
206
208
|
private timeout = 10000;
|
207
|
-
private hostConnectionPromise: Promise<
|
208
|
-
private 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.
|
215
|
+
this.logger.log(`Event "${args[0]}" emitted from host`);
|
214
216
|
this.emit(...args);
|
215
217
|
},
|
216
218
|
};
|
@@ -235,21 +237,29 @@ export class Guest<
|
|
235
237
|
async _connect() {
|
236
238
|
this.emit("beforeconnect", { guest: this });
|
237
239
|
try {
|
238
|
-
const
|
239
|
-
|
240
|
-
|
241
|
-
|
240
|
+
const hostConnectionPromise = connectParentWindow<HostConnection>(
|
241
|
+
{
|
242
|
+
targetOrigin: "*",
|
243
|
+
timeout: this.timeout,
|
244
|
+
logger: this.logger,
|
245
|
+
},
|
246
|
+
this.getLocalMethods()
|
247
|
+
);
|
242
248
|
|
243
|
-
this.hostConnectionPromise =
|
249
|
+
this.hostConnectionPromise = hostConnectionPromise;
|
244
250
|
this.hostConnection = await this.hostConnectionPromise;
|
251
|
+
} catch (e) {
|
252
|
+
this.emit("error", { guest: this, error: e });
|
253
|
+
this.logger.error("Connection failed!", e);
|
254
|
+
return;
|
255
|
+
}
|
256
|
+
try {
|
245
257
|
this.sharedContext = new SharedContext(
|
246
|
-
await this.hostConnection.getSharedContext()
|
258
|
+
await this.hostConnection.getRemoteApi().getSharedContext()
|
247
259
|
);
|
248
|
-
this.debugLogger.log("retrieved sharedContext", this.sharedContext);
|
249
|
-
this.emit("connected", { guest: this, connection });
|
250
260
|
} catch (e) {
|
251
261
|
this.emit("error", { guest: this, error: e });
|
252
|
-
this.
|
262
|
+
this.logger.error("getSharedContext failed!", e);
|
253
263
|
}
|
254
264
|
}
|
255
265
|
}
|