Changelog

Breaking Changes

@interopio/widget

To use the io.Connect widget in your io.Connect Browser project, you no longer need to install the @interopio/widget library per app and pass the IOBrowserWidget factory function to the respective io.Connect library in the Main app or in the Browser Client apps. Also, the channelSelector property of the optional configuration object for widget is deprecated and replaced by a channels property. The channels property accepts as a value an object with the following properties:

Property Type Description
displayMode "all" | "fdc3" Determines which of the available Channels to display (all or only FDC3 ones).
selector object Settings for the Channel Selector UI.

To configure the widget in the Main app, use the widget property in the configuration object for initializing the Main app. Provide URLs pointing to the locations of the widget bundle and styles, any default settings to be passed to client apps, or origins to block from using the widget:

import IOBrowserPlatform from "@interopio/browser-platform";

const config = {
    licenseKey: "my-license-key",
    widget: {
        // It's required to specify the locations of the widget bundle and styles.
        sources: {
            bundle: "https://my-widget/widget-bundle.js",
            styles: ["https://my-widget/styles.css", "https://example.com/custom-styles.css"]
        },
        // Default widget settings that will be used if the Browser Client doesn't provide any.
        defaultConfig: {
            position: "top",
            channels: {
                selector: {
                    enable: true,
                    type: "directional"
                }
            }
        },
        // Origins of Browser Clients to block from using the widget.
        blockList: ["https://example.com/*", "https://another-example.com/*"]
    }
};

const { io } = await IOBrowserPlatform(config);

To request using the widget in a Browser Client app, use the widget property in the Config object for initializing the @interopio/browser:

import IOBrowser from "@interopio/browser";

const options = {
    widget: {
        // Enabling the widget for the current Browser Client app.
        // It's required to specify this to be able to use the widget.
        enable: true,
        // Overriding the default widget settings from the Main app.
        position: "top",
        channels: {
            selector: {
                enable: true,
                type: "default"
            }
        }
    }
};

const io = await IOBrowser(options);

New Features

⚠️ Note that each new feature is listed under all libraries it affects.

@interopio/browser

The following features were added to the @interopio/browser library:

Multiple Channels

io.Connect Browser now provides experimental support for working with multiple Channels simultaneously:

⚠️ Note that this functionality is still experimental and you should take into consideration the following:

  • There may be hidden bugs.
  • There isn't backwards compatibility between the versions of the @interopio/browser and @interopio/browser-platform libraries that support only single Channels and the ones that support both single and multiple Channels. If you want to use multiple Channels, all apps using Channels must be upgraded to the latest version of the @interopio/browser library and the Main app must be upgraded to the latest version of the @interopio/browser-platform library.
  • Supplementary methods for working with multiple Channels have been added to the io.Connect JavaScript FDC3 implementation. These methods are specific io.Connect implementations and are outside the scope of the FDC3 standard. Their purpose is to enable working with multiple Channels in FDC3 apps.

By default, the Channels API is initialized in single Channel mode. To enable multi Channel mode, use the mode property of the channels top-level key in the configuration object for initializing the Main app:

import IOBrowserPlatform from "@interopio/browser-platform";

const config = {
    licenseKey: "my-license-key",
    channels: {
        definitions: [
            // Channel definitions.
        ],
        // Enabling multi Channel mode.
        mode: "multi"
    }
};

const { io } = await IOBrowserPlatform(config);

Added new methods for working with multiple Channels - myChannels(), getMyChannels() and onChannelsChanged(). These methods can be used both in single and in multi Channel mode:

// Retrieving the names of all currently joined Channels.
const channelNames = await io.channels.myChannels();

// Retrieving the contexts of all currently joined Channels.
const channelContexts = await io.channels.getMyChannels();

// Getting notified when the current window joins or leaves a Channel.
// The handler receives as an argument a list of all currently joined Channels.
const handler = (channelNames) => {
    channelNames.forEach(console.log);
};

const unsubscribe = io.channels.onChannelsChanged(handler);

⚠️ Note that the my(), getMy(), and onChanged() methods for working with single Channels aren't deprecated, but it's highly recommended to use the myChannels(), getMyChannels() and onChannelsChanged() methods instead, which support working both with single and multiple Channels.

Exposed a mode property which you can use to determine the current Channel mode (single or multi Channel):

const channelMode = io.channels.mode;

if (channelMode === "single") {
    // Handle Channel operations in single Channel mode.
} else if (channelMode === "multi") {
    // Handle Channel operations in multi Channel mode.
};

The leave() method now accepts as an optional argument an object with optional windowId and channel properties which you can use to specify which window instance from which Channel to remove:

// Specifying a window instance to remove from a specific Channel.
const options = {
    windowId: win.id,
    channel: "Red"
};

await io.channels.leave(options);

Adding FDC3 Channels Dynamically

You can now use the add() method of the Channels API to add FDC3 Channels dynamically:

const myFDC3Channel = {
    name: "Red",
    meta: {
        color: "red",
        fdc3: {
            id: "fdc3.channel.1",
            displayMetadata: {
                name: "Channel 1",
                glyph: "1"
            }
        }
    }
};

const channelContext = await io.channels.add();

API Memoization

It's now possible to configure the @interopio/browser library to be memoized by using the memoizeAPI property of the optional Config object for initializing the library. This way, if the factory function is invoked more than once, the already initialized API object will be returned instead of throwing an error:

import IOBrowser from "@interopio/browser";

const options = {
    // The initialized API object will be remembered and returned
    // if the factory function is invoked more than once.
    memoizeAPI: true
};

const io = await IOBrowser(options);

Intents API

To get notified when Intent handlers are added or removed, use the onHandlerAdded() and onHandlerRemoved() methods respectively on top level of the Intents API. Provide a callback function for handling the event:

const handler = (intentHandler) => {
    console.log(`App "${intentHandler.applicationName}" was registered as an Intent handler.`);
};

const unsubscribe = io.intents.onHandlerAdded(handler);

@interopio/browser-platform

The following features were added to the @interopio/browser-platform library:

Multiple Channels

io.Connect Browser now provides experimental support for working with multiple Channels simultaneously:

⚠️ Note that this functionality is still experimental and you should take into consideration the following:

  • There may be hidden bugs.
  • There isn't backwards compatibility between the versions of the @interopio/browser and @interopio/browser-platform libraries that support only single Channels and the ones that support both single and multiple Channels. If you want to use multiple Channels, all apps using Channels must be upgraded to the latest version of the @interopio/browser library and the Main app must be upgraded to the latest version of the @interopio/browser-platform library.
  • Supplementary methods for working with multiple Channels have been added to the io.Connect JavaScript FDC3 implementation. These methods are specific io.Connect implementations and are outside the scope of the FDC3 standard. Their purpose is to enable working with multiple Channels in FDC3 apps.

By default, the Channels API is initialized in single Channel mode. To enable multi Channel mode, use the mode property of the channels top-level key in the configuration object for initializing the Main app:

import IOBrowserPlatform from "@interopio/browser-platform";

const config = {
    licenseKey: "my-license-key",
    channels: {
        definitions: [
            // Channel definitions.
        ],
        // Enabling multi Channel mode.
        mode: "multi"
    }
};

const { io } = await IOBrowserPlatform(config);

Dynamic Options for Remote Store Requests

You can now provide dynamically a RequestInit object for fetch requests sent to the remote app store defined in the Main app. To provide a custom RequestInit object, use the getRequestInit property of the remote object under the applications top-level key in the configuration for initializing the Main app. The getRequestInit property accepts as a value a function that must return a RequestInit object. The returned object will be merged with the default RequestInit object and will be appended to all requests sent to the the remote app store:

import IOBrowserPlatform from "@interopio/browser-platform";

// Define a function that returns a `RequestInit` object.
const getRequestInit = () => {
    const requestInit = { cache: "no-cache" };

    return requestInit;
};

const config = {
    licenseKey: "my-license-key",
    applications: {
        remote: {
            url: "http://localhost:3001/v2/apps/",
            // The `RequestInit` object returned by your function will be merged with
            // the default one and sent with every request to the remote app store.
            getRequestInit
        }
    }
};

const { io } = await IOBrowserPlatform(config);

Managing Preferences for Apps Without Definitions

You can now use the validNonExistentApps property to configure the App Preferences API to manage preferences for apps that aren't defined in the io.Connect framework:

import IOBrowserPlatform from "@interopio/browser-platform";

const config = {
    licenseKey: "my-license-key",
    // Settings for storing app preferences.
    applicationPreferences: {
        store: {
            type: "local"
        },
        // Provide the names of the apps without definitions in the io.Connect framework
        // for which you want to be able to manage app preferences.
        validNonExistentApps: ["my-app", "my-other-app"]
    }
};

const { io } = await IOBrowserPlatform(config);

// Now you'll be able to manage the preferences for the specified apps that don't have app definitions.
const prefs = { fontSize: 18 };
const options = { app: "my-app" };

await io.prefs.set(prefs, options);

Blocking Origins

To instruct the io.Connect Browser to block specific origins, use the blockList property of the connection top-level key in the configuration object for initializing the Main app:

import IOBrowserPlatform from "@interopio/browser-platform";

const config = {
    licenseKey: "my-license-key",
    // Settings for blocking origins.
    connection: {
        blockList: ["https://example.com/*", "https://another-example.com/*"]
    }
};

const { io } = await IOBrowserPlatform(config);

io.Manager Feature Settings

To control which io.Manager stores (apps, Layouts, app preferences) to retrieve and keep updated, you can now use the features property of the manager top-level key in the configuration object for initializing the Main app. Periodic polling of all stores is enabled by default.

The following example demonstrates how to disable polling the io.Manager app preferences store:

import IOBrowserPlatform from "@interopio/browser-platform";

const config = {
    licenseKey: "my-license-key",
    manager: {
        url: "https://my-io-manager.com:4242/api",
        auth: {
            basic: {
                username: "username",
                password: "password"
            }
        },
        features: {
            // The app preferences store won't be polled for data.
            preferencesStore: false
        }
    }
};

const { io } = await IOBrowserPlatform(config);

The features object has the following properties:

Property Type Description
applicationsStore boolean If true (default), app definitions will be fetched periodically from the io.Manager app store.
layoutsStore boolean If true (default), Layout definitions will be fetched periodically from the io.Manager Layouts store.
preferencesStore boolean If true (default), app preferences will be fetched periodically from the io.Manager app preferences store.

@interopio/fdc3

Multiple Channels in FDC3 Apps

The FDC3 standard doesn't provide out-of-the-box support for multiple Channels. To enable FDC3 apps to work with multiple Channels, the io.Connect JavaScript FDC3 implementation has been extended with the following supplementary methods:

// Retrieving all currently joined Channels.
const currentChannels = await fdc3.getCurrentChannels();

// Leaving a Channel by specified Channel ID.
await fdc3.leave("Red");

// Leaving all currently joined Channels.
await fdc3.leaveCurrentChannels();

The handler passed to the addContextListener() method now receives as a third optional argument a Channel ID. You can use it to determine the Channel from which comes the context update:

const contextType = "Contact";
const handler = (context, metadata, channelId) => {
    console.log(`Received updates from Channel ${channelId}.`);
};

await fdc3.addContextListener(contextType, handler);

FDC3 Context Types

Updated the methods of the io.Connect Channels API to be able to send and receive FDC3 context data in order to facilitate using FDC3 User Channel contexts in non-FDC3 interop-enabled apps.

@interopio/intents-resolver-ui-react

The config object for the <IOConnectIntentsResolverUI /> component now has a settings property which you can use to provide settings for saving Intent handlers:

import IOBrowser from "@interopio/browser";
import IOConnectIntentsResolver from "@interopio/intents-resolver-api";
import IOConnectIntentsResolverUI from "@interopio/intents-resolver-ui-react";
import "@interopio/intents-resolver-ui-react/styles";

const config = {
    libraries: [IOConnectIntentsResolver]
};

const io = await IOBrowser(config);

// Providing settings for saving Intent handlers.
const settings = {
    saveHandler: {
        enabled: true
    }
};

const domElement = document.getElementById("root");
const root = ReactDOM.createRoot(domElement);

root.render(
    // Provide the settings to the component.
    <IOConnectIntentsResolverUI config={{ io, settings }} />
);

@interopio/widget

The configuration object passed to the widget by each Browser Client has the following new properties:

Property Type Description
awaitFactory boolean If true (default), will the library will wait for the IOBrowserWidget() factory function to resolve before completing its initialization.
timeout number Interval in milliseconds to wait for the IOBrowserWidget() factory function to be fetched from the remote source. Defaults to 5000.

@interopio/workspaces-ui-web-components

Implemented the @interopio/workspaces-ui-web-components library based on Web Components. Like the @interopio/workspaces-ui-react package, @interopio/workspaces-ui-web-components can be used for building a custom Workspaces App for io.Connect Browser and io.Connect Browser projects. For details on how to use the library, see the README of the package.

Improvements & Bug Fixes

⚠️ Note that each improvement or bug fix is listed under all libraries it affects.

@interopio/browser

  • Improved error handling for the App Preferences API.

@interopio/browser-platform

  • Added support for "FDC3 for the Web".
  • Added license verification for public and private keys.
  • Added platform origins allow listing.
  • Improved handling the lack of Window Management support in Firefox.

@interopio/fdc3

  • Improved library initialization speed.
  • Improved the behavior of the getOrCreateChannel() method.
  • Fixed a bug where the raiseIntent() method would reuse an existing app instance instead of starting a new one when an app ID was provided as a target.

@interopio/workspaces-api

  • The Workspaces API can now be used in Node.js apps.